吉哥系列故事——恨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无关的数字的平方和。
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),需要维护三个值 之前的符合的数的个数,之前的数的平方和 之前的数的和 然后利用这三个数可以算出加上当前最高位之后的数的平方和