2 条题解
-
0
很明显的一道记搜,三个条件用普通dp不好转移状态 定义一个结构体,分别表示数的个数,总和,平方和 用数学思想即可解决
#include<bits/stdc++.h> //by: hansang.tamoto ring using namespace std; typedef long long LL; const int N=30; const LL P=1e9+7; struct node{ LL cnt, sum, sum2; //个数,总和,平方和 }f[N][10][10]; LL a[N], d[N]; node dfs(int x, int sum, int num, bool lim){ //sum是各个数位的和%7余数,num是数本身%7余数 if(x==0) return (node){sum && num, 0, 0}; //只有两个都不能整除才能算答案 if(!lim && f[x][sum][num].cnt>0) return f[x][sum][num]; int up=lim? a[x]: 9; node ans=(node){0, 0, 0}; for(int i=0; i<=up; i++) if(i!=7){ node no=dfs(x-1, (sum+i)%7, (num*10+i)%7, lim && (i==up)); LL B=i*d[x-1]%P; ans.cnt=(ans.cnt+no.cnt)%P; //个数和直接加上 ans.sum=(ans.sum+no.cnt*B%P+no.sum)%P; //相当于把i接到no里面的数前面,加上cnt*i*10的x-1次方 ans.sum2=((ans.sum2+no.cnt*B%P*B%P)%P+ (no.sum2+2*no.sum%P*B%P)%P)%P; /*重点 假设no中的数为x1~xcnt,我们有x1^2+x2^2+...+xcnt^2 要求(x1+B)^2+(x2+B)^2+...(xcnt+B)^2 拆出来:(x1^2+2*x1*B+B^2)+(x2^2+2*x2*B+B^2)+... +(xcnt^2+2*xcnt*B+B^2) 合并同类项:(x1^2+x2^2+...+xcnt^2)+2*B*(x1+x2+...+xcnt) +cnt*B^2 = sum2+cnt*B^2+2*B*sum */ } if(!lim) f[x][sum][num]=ans; return ans; } LL calc(LL x){ int len=0; while(x>0) a[++len]=x%10, x/=10; return dfs(len, 0, 0, 1).sum2; } int main(){ //freopen("a.in", "r", stdin); d[0]=1; for(int i=1; i<=25; i++) d[i]=d[i-1]*10%P; //预处理10的次方 int T; scanf("%d", &T); while(T--){ LL n, m; scanf("%lld%lld", &n, &m); printf("%lld\n", (calc(m)-calc(n-1)+P)%P); } return 0; } -
0
/* 很明显的一道记搜,三个条件用普通dp不好转移状态 定义一个结构体,分别表示数的个数,总和,平方和 用数学思想即可解决 */ #include<bits/stdc++.h> //by: hansang.tamoto ring using namespace std; typedef long long LL; const int N=30; const LL P=1e9+7; struct node{ LL cnt, sum, sum2; //个数,总和,平方和 }f[N][10][10]; LL a[N], d[N]; node dfs(int x, int sum, int num, bool lim){ //sum是各个数位的和%7余数,num是数本身%7余数 if(x==0) return (node){sum && num, 0, 0}; //只有两个都不能整除才能算答案 if(!lim && f[x][sum][num].cnt>0) return f[x][sum][num]; int up=lim? a[x]: 9; node ans=(node){0, 0, 0}; for(int i=0; i<=up; i++) if(i!=7){ node no=dfs(x-1, (sum+i)%7, (num*10+i)%7, lim && (i==up)); LL B=i*d[x-1]%P; ans.cnt=(ans.cnt+no.cnt)%P; //个数和直接加上 ans.sum=(ans.sum+no.cnt*B%P+no.sum)%P; //相当于把i接到no里面的数前面,加上cnt*i*10的x-1次方 ans.sum2=((ans.sum2+no.cnt*B%P*B%P)%P+ (no.sum2+2*no.sum%P*B%P)%P)%P; /*重点 假设no中的数为x1~xcnt,我们有x1^2+x2^2+...+xcnt^2 要求(x1+B)^2+(x2+B)^2+...(xcnt+B)^2 拆出来:(x1^2+2*x1*B+B^2)+(x2^2+2*x2*B+B^2)+... +(xcnt^2+2*xcnt*B+B^2) 合并同类项:(x1^2+x2^2+...+xcnt^2)+2*B*(x1+x2+...+xcnt) +cnt*B^2 = sum2+cnt*B^2+2*B*sum */ } if(!lim) f[x][sum][num]=ans; return ans; } LL calc(LL x){ int len=0; while(x>0) a[++len]=x%10, x/=10; return dfs(len, 0, 0, 1).sum2; } int main(){ //freopen("a.in", "r", stdin); d[0]=1; for(int i=1; i<=25; i++) d[i]=d[i-1]*10%P; //预处理10的次方 int T; scanf("%d", &T); while(T--){ LL n, m; scanf("%lld%lld", &n, &m); printf("%lld\n", (calc(m)-calc(n-1)+P)%P); } return 0; }
- 1
信息
- ID
- 1821
- 时间
- 1000ms
- 内存
- 512MiB
- 难度
- 7
- 标签
- (无)
- 递交数
- 77
- 已通过
- 16
- 上传者