[HDU4507] [2013TencentHackathon] 吉哥系列故事——恨7不成妻 [數位dp]
這個題目名字是什麼網上衝浪的羞恥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;
}