首先来说,,这题我wrong了好几次,代码力太弱啊。。很多细节没考虑。。
题意:给定两个数 L R,1 <= L <= R <= 10^18 ;求L 到 R 间 与 7 无关的数的平方和
什么数与7 无关?
1 没有数字7
2 不是7的倍数
3 所有数字的和不是7的倍数
我们先来考虑一下 如果这题问的是: L 到 R 间 与7 无关的数有多少个?
这道题该怎么思考? 给一点提示 dp 方程可以写成三维的 num(i,j,k) 其中 i 代表数的位数 j 代表 这个数对7取模的余数 k 代表这个数所有数字和对7取模的值,至于num(i,j,k) 当让就是这种数的个数了, 方程的转化也很简单 从数末尾逐步填数字 l (0~9)的话 num(i+1,(j*10+l)%7,(k+l)%7)+=num(i,j,k);
接下来 我默认你知道 num[i][j][k] 该怎么求了 这个时候 再来考虑一下 L 到 R 间与7 无关的数的和 ? 这个时候不用考虑的太复杂,,因为首先,你在求num[i][j][k]的时候已经求出了所有的满足条件的数的所有可能,要求和,无非就是哪一位的那个数字有多少个。
如果我们的dp是逐步往数的末尾填数 ,这个时候可以这样写 sum(i,j,k)其中i,j,k和num的i,j,k一个意思,然后sum表示满足这种情况的数的和 方程的转换可以写为:同样从数末尾逐步填数字 l (0~9)-- num(i+1,(j*10+l)%7,(k+l)%7)+=sum(i,j,k)*10+num(i,j,k)*l;
再来考虑平方和就比较容易了,,我们知道如果前面的数是a 我们往后面塞一个数字l 那么我们要求的数的平方和是---(10*a+l)^2 也就是100*a*a+20*a*l+l*l
方程我就不写了,,然后接下来的思路都是和上面的类似
贴出渣渣的代码。。。
1 #include<iostream> 2 #include<stdio.h> 3 #include<string.h> 4 #include <string> 5 #include <cmath> 6 #include <algorithm> 7 #include <map> 8 #include <set> 9 #include <queue> 10 #include <stack> 11 #include<stdlib.h> 12 #include <vector> 13 using namespace std; 14 #pragma comment(linker, "/STACK:1024000000,1024000000") 15 #define ll __int64 16 #define CL(a,b) memset(a,b,sizeof(a)) 17 #define MAXNODE 100010 18 ll MOD=1000000007; 19 20 ll s,e; 21 22 ll dp[30][7][7]; 23 ll wsu[30][7][7]; 24 ll num[30][7][7]; 25 ll val[30]; 26 void initval() 27 { 28 int i=0; 29 val[1]=1; 30 val[0]=0; 31 for(i=2;i<=19;i++) 32 { 33 val[i]=val[i-1]*10; 34 } 35 } 36 37 void initdp() 38 { 39 int i,j,k,l; 40 CL(dp,0); 41 CL(num,0); 42 CL(wsu,0); 43 for(i=0;i<10;i++) 44 { 45 if(i==7)continue; 46 dp[1][i%7][i%7]+=i*i; 47 wsu[1][i%7][i%7]+=i; 48 num[1][i%7][i%7]++; 49 } 50 num[0][0][0]=1; 51 for(i=1;i<29;i++) 52 { 53 for(j=0;j<7;j++) 54 { 55 for(k=0;k<7;k++) 56 { 57 for(l=0;l<10;l++) 58 { 59 if(l==7)continue; 60 num[i+1][(j+l)%7][(k*10+l)%7]+=num[i][j][k]%MOD; 61 num[i+1][(j+l)%7][(k*10+l)%7]%=MOD; 62 wsu[i+1][(j+l)%7][(k*10+l)%7]+=(wsu[i][j][k]*(ll)10+(ll)l*(num[i][j][k]))%MOD; 63 wsu[i+1][(j+l)%7][(k*10+l)%7]%=MOD; 64 dp[i+1][(j+l)%7][(k*10+l)%7]+=(((ll)l*(ll)l*num[i][j][k])+dp[i][j][k]*100+(ll)2*(ll)l*wsu[i][j][k]*(ll)10)%MOD; 65 dp[i+1][(j+l)%7][(k*10+l)%7]%=MOD; 66 } 67 // printf("%d %d %d %I64d\n",i,j,k,dp[i][j][k]); 68 } 69 } 70 } 71 } 72 73 ll pro(ll n) 74 { 75 if(n==0)return 0; 76 ll rem=0; 77 ll nu[30]; 78 int w,i,j,k; 79 nu[0]=0; 80 ll tem=n,va;w=1,rem=0; 81 while(tem!=0) 82 { 83 nu[w]=tem%10; 84 tem/=10; 85 w++; 86 } 87 va=0; 88 int su=0; 89 ll v=0; 90 while(--w) 91 { 92 if(nu[w]==7) 93 { 94 for(i=1;i<w;i++)nu[i]=9; 95 nu[w]=6; 96 } 97 for(i=nu[w]-1;i>=0;i--) 98 { 99 if(i==7)continue; 100 for(j=0;j<7;j++) 101 { 102 for(k=0;k<7;k++) 103 { 104 if((su+i+j)%7==0)continue; 105 if(((ll)v+(ll)i*val[w]+(ll)k)%7==0)continue; 106 ll pre=(va+(ll)i*(val[w]%MOD))%MOD; 107 pre%=MOD; 108 rem+=(((pre*pre)%MOD)*(num[w-1][j][k]%MOD))%MOD; 109 rem%=MOD; 110 rem+=dp[w-1][j][k]%MOD;; 111 rem%=MOD; 112 rem+=((((ll)2*pre)%MOD)*wsu[w-1][j][k]%MOD)%MOD; 113 rem%=MOD; 114 } 115 } 116 } 117 rem%=MOD; 118 va+=(nu[w]*(val[w]%MOD))%MOD; 119 va%=MOD; 120 v+=nu[w]*(val[w]%7); 121 v%=7; 122 su+=nu[w]; 123 su%=7; 124 } 125 if(v!=0&&su!=0)rem+=(va*va)%MOD; 126 return rem%MOD; 127 } 128 129 int main() 130 { 131 int tt; 132 initval(); 133 initdp(); 134 scanf("%d",&tt); 135 while(tt--) 136 { 137 scanf("%I64d %I64d",&s,&e); 138 ll rs=pro(s-1LL); 139 ll re=pro(e); 140 ll rem=re-rs; 141 rem=rem%MOD; 142 if(rem<0)rem+=MOD; 143 // printf("%I64d %I64d ",rs,re); 144 printf("%I64d\n",rem); 145 } 146 return 0; 147 }