首页 > 代码库 > HDU - 4507 吉哥系列故事――恨7不成妻 (数位DP)
HDU - 4507 吉哥系列故事――恨7不成妻 (数位DP)
Description
单身!
依然单身!
吉哥依然单身!
DS级码农吉哥依然单身!
所以,他生平最恨情人节,不管是214还是77,他都讨厌!
吉哥观察了214和77这两个数,发现:
2+1+4=7
7+7=7*2
77=7*11
最终,他发现原来这一切归根到底都是因为和7有关!所以,他现在甚至讨厌一切和7有关的数!
什么样的数和7有关呢?
如果一个整数符合下面3个条件之一,那么我们就说这个整数和7有关――
1、整数中某一位是7;
2、整数的每一位加起来的和是7的整数倍;
3、这个整数是7的整数倍;
现在问题来了:吉哥想知道在一定区间内和7无关的数字的平方和。
依然单身!
吉哥依然单身!
DS级码农吉哥依然单身!
所以,他生平最恨情人节,不管是214还是77,他都讨厌!
吉哥观察了214和77这两个数,发现:
2+1+4=7
7+7=7*2
77=7*11
最终,他发现原来这一切归根到底都是因为和7有关!所以,他现在甚至讨厌一切和7有关的数!
什么样的数和7有关呢?
如果一个整数符合下面3个条件之一,那么我们就说这个整数和7有关――
1、整数中某一位是7;
2、整数的每一位加起来的和是7的整数倍;
3、这个整数是7的整数倍;
现在问题来了:吉哥想知道在一定区间内和7无关的数字的平方和。
Input
输入数据的第一行是case数T(1 <= T <= 50),然后接下来的T行表示T个case;每个case在一行内包含两个正整数L, R(1 <= L <= R <= 10^18)。
Output
请计算[L,R]中和7无关的数字的平方和,并将结果对10^9 + 7 求模后输出。
Sample Input
3 1 9 10 11 17 17
Sample Output
236 221 0
Source
2013腾讯编程马拉松初赛第一场(3月21日)
思路:数位DP, 一个表示与7无关的个数,一个表示与7无关的数的和,7无关的数字的平方和。
难处理的是平方和,要从前两个推出来,就是将平方和拆出来就行了,还有乱mod不会过啊,
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <queue> using namespace std; typedef long long ll; const int maxn = 20; const ll mod = 1000000007ll; struct node { long long cnt; long long sum; long long sqsum; } dp[maxn][10][10]; ll p[maxn]; int num[maxn]; node dfs(int cur, int p1, int p2, int flag) { if (cur == -1) { node tmp; tmp.cnt = (p1 != 0 && p2 != 0); tmp.sum = tmp.sqsum = 0; return tmp; } if (!flag && dp[cur][p1][p2].cnt != -1) return dp[cur][p1][p2]; int end = flag?num[cur]:9; node ans; node tmp; ans.cnt = ans.sqsum = ans.sum = 0; for (int i = 0; i <= end; i++) { if (i == 7) continue; tmp = dfs(cur-1, (p1+i)%7, (p2*10+i)%7, flag&&i==end); ans.cnt += tmp.cnt; ans.cnt %= mod; ans.sum += (tmp.sum+ ((p[cur]*i)%mod)*tmp.cnt%mod)%mod; ans.sum %= mod; ans.sqsum += (tmp.sqsum + ((2*p[cur]*i)%mod)*tmp.sum)%mod; ans.sqsum %= mod; ans.sqsum += (tmp.cnt*p[cur])%mod*p[cur]%mod*i*i%mod; ans.sqsum %= mod; } if (!flag) dp[cur][p1][p2] = ans; return ans; } long long cal(long long m) { int cnt = 0; while (m) { num[cnt++] = m%10; m /= 10; } return dfs(cnt-1, 0, 0, 1).sqsum; } int main() { int t; p[0] = 1; for (int i = 1; i < maxn; i++) p[i] = (p[i-1]*10) % mod; for (int i = 0; i < maxn; i++) for (int j = 0; j < 10; j++) for (int k = 0; k < 10; k++) dp[i][j][k].cnt = -1; cin >> t; while (t--) { ll l, r; cin >> l >> r; long long ans = cal(r); ans -= cal(l-1); ans = (ans%mod+mod)%mod; cout << ans << endl; } return 0; }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。