51Nod-1230-幸运数
2017-06-14 20:58
183 查看
ACM模版
先进行素数筛,然后设 dp[i][j][k] 表示前 i 位,和为 j,平方和为 k,然后进行树归就 OK 了!和普通的数位 dp 相差就是一个素数筛和多了一个维度而已,这里由于最多 18 位,所以和最大为 162,平方和最大为 1458,空间要求不是太多,所以没有什么特别的需求,数位 DP 的核心实际上是记忆化操作,不然就和普通的搜索无异了!
以前写数位 DP 都是用的非递归形式,现在看来,感觉还是树归最容易写了~~~
描述
题解
典型的数位 DP 问题,也是树归~~~先进行素数筛,然后设 dp[i][j][k] 表示前 i 位,和为 j,平方和为 k,然后进行树归就 OK 了!和普通的数位 dp 相差就是一个素数筛和多了一个维度而已,这里由于最多 18 位,所以和最大为 162,平方和最大为 1458,空间要求不是太多,所以没有什么特别的需求,数位 DP 的核心实际上是记忆化操作,不然就和普通的搜索无异了!
以前写数位 DP 都是用的非递归形式,现在看来,感觉还是树归最容易写了~~~
代码
#include <iostream> #include <cstring> #include <cstdio> using namespace std; typedef long long ll; const int MAXD = 20; const int MAXN = 1500; const int MAXM = 163; /* * 素数筛选,判断小于MAXN的数是不是素数 * notprime是一张表,false表示是素数,true表示不是 */ int dig[MAXN]; bool notprime[MAXN]; ll dp[MAXD][MAXM][MAXN], L, R; // dp[i][j][k] i 位 j 和 k 平方和 void init() { memset(notprime, false, sizeof(notprime)); memset(dp, -1, sizeof(dp)); notprime[0] = notprime[1] = true; for (int i = 2; i < MAXN; i++) { if (!notprime[i]) { if (i > MAXN / i) // 阻止后边i * i溢出(或者i,j用long long) { continue; } // 直接从i * i开始就可以,小于i倍的已经筛选过了 for (int j = i * i; j < MAXN; j += i) { notprime[j] = true; } } } } ll dfs(int pos, int sum, int sqrt_sum, int flag) { if (pos < 0) { return (!notprime[sum]) && (!notprime[sqrt_sum]); } if (!flag && dp[pos][sum][sqrt_sum] != -1) { return dp[pos][sum][sqrt_sum]; } ll res = 0; int lim = flag ? dig[pos] : 9; for (int i = 0; i <= lim; i++) { res += dfs(pos - 1, sum + i, sqrt_sum + i * i, flag && (i == lim)); } if (!flag) { dp[pos][sum][sqrt_sum] = res; } return res; } ll solve(ll n) { int len = 0; while (n) { dig[len++] = n % 10; n /= 10; } return dfs(len - 1, 0, 0, 1); } int main(void) { init(); int T; cin >> T; while (T--) { scanf("%lld%lld", &L, &R); printf("%lld\n", solve(R) - solve(L - 1)); } return 0; }
相关文章推荐
- 51nod 1230:幸运数
- 51nod 1230 幸运数 数位dp
- 51nod 1230 幸运数 数位dp
- 程序输入幸运数
- 【51NOD-0】1137 矩阵乘法
- 幸运数——庞果网
- 后缀数组——51nod 1732 51nod婚姻介绍所
- HDU 1230 火星A+B
- 51nod 1483 化学变换 (枚举+bfs or 枚举+技巧)
- 杭电 1230 火星A+B
- [广义后缀自动机 SG值] 51Nod 1869 那些年,我们一起讲的故事
- hdu-oj 1230 火星A+B
- 51Nod-1051 最大子矩阵和【最大子段和+DP】
- 51nod -1090 . 3个数和为0 && 1267 . 4个数和为0
- 51nod 1327 棋盘游戏
- 51nod 1278 相离的圆(排序+修改步长)
- 【51NOD】数字1的数量
- hdu 1230 字符串
- 51Nod-1394-差和问题
- 51nod 1298 圆与三角形