吉哥系列故事——恨7不成妻
Time Limit : 1000/500ms (Java/Other) Memory Limit : 65535/32768K (Java/Other)
Total Submission(s) : 16 Accepted Submission(s) : 3
Problem Description
单身!
依然单身!
吉哥依然单身!
DS级码农吉哥依然单身!
所以,他生平最恨情人节,不管是214还是77,他都讨厌!
吉哥观察了214和77这两个数,发现:
2+1+4=7
7+7=7*2
77=7*11
最终,他发现原来这一切归根到底都是因为和7有关!所以,他现在甚至讨厌一切和7有关的数!
什么样的数和7有关呢?
如果一个整数符合下面3个条件之一,那么我们就说这个整数和7有关——
1、整数中某一位是7;
2、整数的每一位加起来的和是7的整数倍;
3、这个整数是7的整数倍;
现在问题来了:吉哥想知道在一定区间内和7无关的数字的平方和。
依然单身!
吉哥依然单身!
DS级码农吉哥依然单身!
所以,他生平最恨情人节,不管是214还是77,他都讨厌!
吉哥观察了214和77这两个数,发现:
2+1+4=7
7+7=7*2
77=7*11
最终,他发现原来这一切归根到底都是因为和7有关!所以,他现在甚至讨厌一切和7有关的数!
什么样的数和7有关呢?
如果一个整数符合下面3个条件之一,那么我们就说这个整数和7有关——
1、整数中某一位是7;
2、整数的每一位加起来的和是7的整数倍;
3、这个整数是7的整数倍;
现在问题来了:吉哥想知道在一定区间内和7无关的数字的平方和。
Input
输入数据的第一行是case数T(1 <= T <= 50),然后接下来的T行表示T个case;每个case在一行内包含两个正整数L, R(1 <= L <= R <= 10^18)。
Output
请计算[L,R]中和7无关的数字的平方和,并将结果对10^9 + 7 求模后输出。
Sample Input
3 1 9 10 11 17 17
Sample Output
236 221 0
#include <stdio.h> #include<string> #include<algorithm> #include<math.h> using namespace std; const long long MOD=1000000007LL; struct node{ long long num; long long sum; long long qsum; }; node dp[41][33][33];//数位 每位的数 整个数 long long p[30]; int bit[41]; node dfs(int pos,int sta,int sta1,bool limit) { if(pos==-1) { node a; a.num=(sta!=0&&sta1!=0); a.sum=0; a.qsum=0; return a; } if(dp[pos][sta][sta1].num!=-1&&!limit) { return dp[pos][sta][sta1]; } int up=limit?bit[pos]:9; node ans; ans.num=0,ans.sum=0,ans.qsum=0; int i; for(i=0;i<=up;i++) { if(i==7)continue; node temp=dfs(pos-1,(sta+i)%7,(sta1*10+i)%7,limit&&i==up); ans.num+=temp.num;//数量 ans.num%=MOD; ans.sum+=((i%MOD*p[pos]%MOD*temp.num%MOD+temp.sum)%MOD);//和 ans.sum%=MOD; ans.qsum+=(temp.qsum%MOD+temp.num%MOD*(i%MOD*p[pos]%MOD)%MOD*(i%MOD*p[pos]%MOD)+2*i%MOD*p[pos]%MOD*temp.sum%MOD); ans.qsum%=MOD; } if(!limit) dp[pos][sta][sta1]=ans; return ans; } long long solve(long long x) { int cnt=0; while(x) { bit[cnt++]=x%10; x/=10; } return dfs(cnt-1,0,0,1).qsum; } int main(int argc, char *argv[]) { p[0]=1; for(int i=1;i<30;i++) { p[i]=(p[i-1]*10)%MOD; } int t,i,j,k; for(i=0;i<41;i++) { for(j=0;j<33;j++) { for(k=0;k<33;k++) { dp[i][j][k].num=-1; } } } scanf("%d",&t); while(t--) { long long n,m; scanf("%lld %lld",&n,&m); long long ans=solve(m)%MOD; ans-=(solve(n-1)%MOD); ans=(ans+MOD)%MOD; printf("%lld\n",ans); } return 0; }因为可能会大的数取模后小于小的数取模所以需要(ans+mod),需要维护三个值 之前的符合的数的个数,之前的数的平方和 之前的数的和 然后利用这三个数可以算出加上当前最高位之后的数的平方和