这个题目名字是什么网上冲浪的羞耻play吗(
乍一看好像是道数位dp;然而要求的是平方和。
在暂时没有其他思路的情况下——能不能用数位dp做平方和?
数位dp在搜索的时候是这么个样子的:比如说
abcdefghi
现在搜到:
9982|e|fghi
那么现在确定了前面的9982,当前这一位和之后的fghi都不确定。
在这一位上的搜索结果就覆盖了efghi所有的可行情况
那么很显然地,要求数的平方和也就是这个(9982efghi)的平方和
所以就是(998200000+efghi)的平方和。这个可以拆。
拆出来三个都可以求。
(998200000²想必不用多说;
2×998200000×efghi只需要知道sum(efghi),这个也好求;
efghi²呢?注意到这也是平方和,改变现在的问题让这个变成子问题就好了。)
这道题的细节有点多。
仔细讨论一下吧,理清思路再敲键盘。
现在这道题目被拆解为六块,分别是三个条件和三个返回值。
三个条件:
1.不能有某一位是7;
2.数位和不被7整除;
3.数不被7整除
对应的方法:
1.在枚举当前数位的时候直接跳过
if (i==7) continue;
2.传递数位和对7取模的余数sum
3.传递(当前确定下来的一部分)数对7取模的余数ori
if (!pos) ... sum && ori ...
三个值:
1.满足条件数的个数cnt=a
2.满足条件数的和sum=b
3.满足条件数的平方和sqr=c
对应地,枚举令
位置上的值为
,有方程:
(以下记
为
,记
为
。)
1:
2:
3:
然后往里面放无数个mod((
边界:!pos
时,return Struct_UserDefined(sum&&ori, 0, 0);
大家好 我是会忘记读入数据组数的那种傻吊
还会把1e9+7写成1e9+9的那种
还有两个很蠢的错误不过不是很好描述就不讲了
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<queue>
#include<cmath>
#include<ctime>
using namespace std;
const long long mod = 1000000007;
long long bit[20];
long long tp[20];
struct sut {
long long a, b, c;
sut(long long x = 0, long long y = 0, long long z = 0) {
a = x;
b = y;
c = z;
}
} F[20][10][10];
sut dfs(int pos, int sum, int ori, bool limit) {
if (!pos) return sut(sum && ori, 0, 0);
if (!limit && F[pos][sum][ori].a != -1) return F[pos][sum][ori];
sut ret, tmp;
long long up = limit ? bit[pos] : 9;
for (long long i = 0; i <= up; ++i) {
if (i == 7) continue;
tmp = dfs(pos - 1, (sum + i) % 7, (ori * 10 + i) % 7, limit && i == up);
ret.a += tmp.a;
ret.a %= mod;
ret.b += (tmp.a * i % mod * tp[pos-1] % mod + tmp.b) % mod;
ret.b %= mod;
ret.c += tmp.a * i % mod * i % mod * tp[pos-1] % mod * tp[pos-1] % mod;
ret.c %= mod;
ret.c += (2ll * i % mod * tp[pos-1] % mod * tmp.b % mod + tmp.c % mod) % mod;
ret.c %= mod;
// cout << pos << " " << sum << " " << ori << " " << limit << " " << i << " " << ret.a << " " << ret.b << " " << ret.c << endl;
}
if(!limit) F[pos][sum][ori] = ret;
return ret;
}
long long solve(long long x) {
bit[0] = 0;
while (x) {
bit[++bit[0]] = x % 10;
x /= 10;
}
return dfs(bit[0], 0, 0, true).c;
}
int main() {
memset(F,-1,sizeof(F));
tp[0] = 1;
for (int i = 1; i <= 19; ++i) tp[i] = tp[i-1] * 10 % mod;
int T;
scanf("%d", &T); //**
while (T--) {
long long L, R;
scanf("%lld%lld", &L, &R);
printf("%lld\n", (solve(R) - solve(L-1) + mod) % mod);
}
return 0;
}