首页 > 代码库 > HDU 4507 吉哥系列故事——恨7不成妻 数位DP
HDU 4507 吉哥系列故事——恨7不成妻 数位DP
这个不是求的数量,而是求平方和,所以记忆化的时候不能像以前那样无脑的来。
先来看简单的情况,如果是求和,应该怎么搞。
假如我现在搜索到第3位,一共有5位,情况应该是这样的XXiXX,注意后面的X和前面的X都是不确定的,转移的时候应该是i * 10^(5-3) * (能满足的条件的数的数量) + sigma((每个分支下面满足条件的数量)* (分支和))这样的形式,然后再返回到上一层。这样子就可以记忆化了。但是除了要统计数量,还要统计和。
那么这里要统计平方和的话,如果还是上面这种情况,根据(a + b)^2 = a^2 + 2*a*b + b^2可以得出(i * 10^(5 - 3))^2 * (能满足的条件的数的数量) + 2 * sigma((每个分支下面满足条件的数量)*(分支和)) + sigma(分支平方和)。所以出了要维护分支和,还要维护分支平方和和数量。
真鬼畜
#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>#include <climits>#include <string>#include <iostream>#include <map>#include <cstdlib>#include <list>#include <set>#include <queue>#include <stack>using namespace std;typedef long long LL;const int maxn = 20;const LL MOD = 1e9 + 7;int lim[maxn],len = 0;LL p10[maxn] = {1};struct EE { LL sqsum,sum,cnt; bool vis; EE(LL sqsum = 0,LL sum = 0,LL cnt = 0):sqsum(sqsum),sum(sum),cnt(cnt),vis(0) {}};EE f[maxn][10][10];void getlim(LL num) { len = 0; memset(lim,0,sizeof(lim)); while(num) { lim[len++] = num % 10; num /= 10; }}EE dfs(int now,int bitsum,int rest,int bound,LL num) { if(now == 0) { if(bitsum % 7 == 0 || rest % 7 == 0) return EE(0,0,0); return EE(0,0,1); } EE ¬e = f[now][bitsum][rest]; if(note.vis && !bound) return note; int m = bound ? lim[now - 1] : 9; EE ret(0,0,0); for(int i = 0;i <= m;i++) { if(i == 7) continue; int nbitsum = (bitsum + i) % 7; int nrest = (rest * 10 + i) % 7; int nbound = (i == m && bound); EE nret = dfs(now - 1,nbitsum,nrest,nbound,num * 10 + i); LL ff = p10[now - 1] * i % MOD; ret.cnt = (nret.cnt + ret.cnt) % MOD; ret.sum = ((nret.cnt * ff % MOD + nret.sum) % MOD + ret.sum) % MOD; ret.sqsum = ((nret.cnt * ff % MOD * ff % MOD + nret.sqsum) % MOD + 2 * ff % MOD * nret.sum % MOD + ret.sqsum) % MOD ; } if(!bound) note = ret,note.vis = true; return ret;}LL work(LL num) { for(int i = 0;i < maxn;i++) { for(int j = 0;j < 10;j++) { for(int k = 0;k < 10;k++) { f[i][j][k] = EE(); } } } getlim(num); EE ret = dfs(len,0,0,1,0); return ret.sqsum;}int main() { for(int i = 1;i < maxn;i++) p10[i] = p10[i - 1] * 10; int T; cin >> T; LL n,m; while(T--) { cin >> n >> m; cout << (work(m) - work(n - 1) + MOD) % MOD << endl; } return 0;}
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。