【GDKOI2012模拟02.01】数字
想了2个小时。。。都想到数位DP去了,虽然没打(但是我疯了)
打表找规律。比赛时打了个表发现每九个的D()都是一循环(1~9)
然后想着怎么做,先打了个暴力然后在想,没想到的是:
如果x为喜欢的数的话,那么x+22680也是喜欢的数。
为什么?
设x=a·D(a),那么x+22680=a·D(a)+22680
因为D(a)为1~9中的一个,所以D(a)为22680的倍数
那么a*D(a)+22680=(a+22680/D(a))*D(a),所以没有问题!
所以我们只需要先预处理一下1~22680的喜欢的数即可。
每次l~r手动统计答案即可。
上标:
#include<cstdio>
#include<cstring>
#define ll long long
#define L 22680
using namespace std;
ll l,r,ans=0;
int T,b[22681],tot=0;
int D(int x) {return (x-1)%9+1;}
int main()
{
//	freopen("number.in","r",stdin);
//	freopen("number.out","w",stdout);
	for (int i=1;i<=L;i++)
	{
		bool bz=0;
		if (i%9==0 && D(i/9)==9) bz=1;
		else if (i%8==0 && D(i/8)==8) bz=1;
		else if (i%7==0 && D(i/7)==7) bz=1;
		else if (i%6==0 && D(i/6)==6) bz=1;
		else if (i%5==0 && D(i/5)==5) bz=1;
		else if (i%4==0 && D(i/4)==4) bz=1;
		else if (i%3==0 && D(i/3)==3) bz=1;
		else if (i%2==0 && D(i/2)==2) bz=1;
		else if (D(i)==1) bz=1;
		if (bz) b[++tot]=i;
	}
	scanf("%d",&T);
	while (T--)
	{
		scanf("%lld %lld",&l,&r);
		ll fir=l/L*L,sec=0;ans=0;
		for (int i=1;i<=tot;i++)
		{
			sec=fir+b[i];
			if (sec<l)
			{
				sec+=L;
				if (sec<=r) ans+=(r-sec)/22680+1;
				continue;
			}
			if (sec>r) break;
			ans+=(r-sec)/22680+1;
		}
		printf("%lld\n",ans);
	}
	return 0;
}
    转载需注明出处。
 
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号