Description
快要到七夕了,又到了交(nue)往(gou)的季节。
恶梦坐在教室里,作为一个纯屌丝的他当然不会关心要送什么礼物给女生,然而他的前桌yves却在忙碌着各种各样的的短信。
恶梦注意到yves发短信给的电话号码似乎都满足着特别的性质,难道yves的"好朋友"是满足正态分布的?
由于yves有着自己最喜欢的数字a,2 <= a <= 9
恶梦从这里入手,发现了一些端倪。
假设yves发的电话号码是一个十进制数字S
恶梦发现S会满足以下三个性质中的一个
1. S是a的倍数。
2. S在十进制表示下的各项数字加起来是a的倍数。
3. S的某一位是a
比如说当a = 7时,21,16,17这三个数字都是会被yves发短信的,他们分别满足1,2,3性质。
恶梦很担心所有的女同学都被yves抢走了,但他一下子又数不过来那些同学没有被yves抢走,所以他把这个问题交给了你。
他会给你两个自然数L,R,以及yves最喜欢的数字a,
他并不希望你告诉他在[L,R]中有多少个同学没有被抢走,而希望你告诉他这些数字的平方和。
比如说3,7是合法的,那么你应该输出3^2 + 7^2 = 58这个数。
当然,由于答案可能很大,你只需要将答案对10^9 + 7取模即可。
Input
输入的第一行包括一个正整数T,表示总共有T组询问。
接下来有T行,每行三个整数L,R,A。
Output
输出包括T行,每行一个整数,表示对10^9 + 7取模的答案。
Sample Input
32 20 63 203 711 771 2
Sample Output
1884159326932817226
Data Constraint
对于15%的数据,0 <= L <= R <= 10^6,T = 1
对于35%的数据,0 <= L <= R <= 10^7,T = 1
另外有25%的数据,A = 2,L = 10^k,R = 10^v,k和v都是自然数。
对于100%的数据,0 <= L <= R <= 10^18,2 <= A <= 9, T <= 100
分析
因为答案显然可以ans[r]-ans[l-1],所以我们只考虑r
设f[i][same][mod][sum]为当前数的前i位与r的前i位相同,当前处理位与r的当前位是否相同(same),当前数对a的模为mod,当前数位的和对a的模为sum时的数字个数
然后转移边界就是当前位数字不能为a,当前位数字不能大于r的当前位
s,g分别为总和和平方和,平方和可以简单地用(x1+1)^2+(x2+1)^2+(x3+1)^2=x1^2+x2^2+x3^2+2*1*(x1+x2+x3)+3*1*1计算
最后答案为f[1][same][mod][sum]的总和,其中mod,sum!=0
#include <iostream> #include <cstdio> #include <memory.h> using namespace std; typedef long long ll; const ll P=1e9+7; int t,a; ll l,r; int c[20],cnt; ll f[3][20][2][10][10]; ll Calc(ll x) { memset(f,0,sizeof f);cnt=0; while (x) c[++cnt]=x%10ll,x/=10ll; f[0][cnt+1][1][0][0]=1; for (int i=cnt;i;i--) for (int same=0;same<2;same++) for (int mo=0;mo<a;mo++) for (int sum=0;sum<a;sum++) if (f[0][i+1][same][mo][sum]) for (int ch=0;ch<10;ch++) if (ch!=a&&(same&&ch<=c[i]||!same)) { bool same1=same&&c[i]==ch; int mo1=(mo*10+ch)%a,sum1=(sum+ch)%a; (f[0][i][same1][mo1][sum1]+=f[0][i+1][same][mo][sum])%=P; (f[1][i][same1][mo1][sum1]+=f[1][i+1][same][mo][sum]*10ll%P+f[0][i+1][same][mo][sum]*ch)%=P; (f[2][i][same1][mo1][sum1]+=f[2][i+1][same][mo][sum]*100ll%P+f[1][i+1][same][mo][sum]*ch*20ll%P+ch*ch*f[0][i+1][same][mo][sum]%P)%=P; } ll ans=0; for (int same=0;same<2;same++) for (int mo=1;mo<a;mo++) for (int sum=1;sum<a;sum++) (ans+=f[2][1][same][mo][sum])%=P; return ans; } int main() { for (scanf("%d",&t);t;t--) { scanf("%lld%lld%d",&l,&r,&a); printf("%lld\n",(Calc(r)-Calc(l-1)+P)%P); } }
原文地址:https://www.cnblogs.com/mastervan/p/10335995.html