1. 程式人生 > >jzoj2700-數字【數論,LCM】

jzoj2700-數字【數論,LCM】

正題

luogu題目連結:https://www.luogu.org/problemnew/show/P4193


題目大意

定義一個函式 D ( x ) D(x) S

( x ) S(x) S ( x ) S(x)
表示 x x 的各位之和
D ( n ) =
{ D ( S ( n ) ) , S 10 S ( n ) D(n)=\left\{\begin{matrix} \\D(S(n)),S\geq 10 \\S(n) \\ \\ \end{matrix}\right.

L R L\sim R 之間有多個 x x 滿足 x = D ( k ) k x=D(k)*k


解題思路

因為 ( n S ( n ) )   m o d   9 = 0 (n-S(n))\ mod\ 9=0 ,所以 D ( n ) = ( n 1 )   m o d   9 + 1 D(n)=(n-1)\ mod\ 9+1
22680   m o d   x = 0 ( x [ 1..9 ] ) 22680\ mod\ x=0(x\in [1..9])
若一個數 n = D ( k ) k n=D(k)*k ,那麼 n + 22680 = ( k + 22680 D ( k ) ) D ( k ) n+22680=(k+\frac{22680}{D(k)})*D(k)
證明:

( k + 22680 D ( k ) ) D ( k ) k D ( k ) = 22680 (k+\frac{22680}{D(k)})*D(k)-k*D(k)=22680
( k + 22680 D ( k ) k ) D ( k ) = 22680 (k+\frac{22680}{D(k)}-k)*D(k)=22680
( k + 22680 D ( k ) k ) D ( k ) = 22680 (k+\frac{22680}{D(k)}-k)*D(k)=22680
k D ( k ) + 22680 k D ( k ) = 22680 k*D(k)+22680-k*D(k)=22680
22680 = 22680 22680=22680
證畢

然後之間根據迴圈節預處理 1 22680 1\sim 22680 的就好了


c o d e code

#include<cstdio>
#define LCM 22680
#define ll long long
using namespace std;
ll n,f[1000000],ans;
ll D(ll x)
{return (x-1)%9+1;}
ll ask(ll x)//1~x的個數
{return x/LCM*ans+f[x%LCM];}
int main()
{
	scanf("%lld",&n);
	for(ll i=1;i<=LCM;i++)//預處理
	{
		for(ll j=1;j<=9;j++)
		    if(D(i/j)==j&&i%j==0){
		    	f[i]=1;
		    	ans++;
		    	break;
			}
		f[i]+=f[i-1];
	}
	while(n--)
	{
		ll l,r;
		scanf("%lld%lld",&l,&r);
		printf("%lld\n",ask(r)-ask(l-1));
	}
}