博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
AcDream 1083 完美数 数位DP
阅读量:5051 次
发布时间:2019-06-12

本文共 3277 字,大约阅读时间需要 10 分钟。

题意:询问一个区间内要么只包含3,要么只包含8的数有多少个?

解法:数位DP,可惜比赛的时候忘了怎么写了,随便写了个DP没有过,后来才调过了。正确解法是开设一个状态:

   f[i][0]表示剩下i+1位数中且暂时不含有3,8的满足要求的数的个数(i位数字可从全0取到全9,后同)
   f[i][1]表示剩下i+1位数中且暂时只含有3的满足要求的数的个数
   f[i][2]表示剩下i+1位数中且暂时只含有8的满足要求的数的个数
   f[i][3]表示剩下i+1位数中且已经含有3和8的满足要求的数的个数,该结果恒为零
   标程的解法使用了位运算来计算状态,非常清爽。

代码如下:

#include 
#include
#include
#include
#include
using namespace std;int f[15][4], bit[15];int new_s(int s, int i) { if (i == 3) return s | 1; if (i == 8) return s | 2; return s;}int dfs(int p, int s, int e) { if (p == -1) { return s == 1 || s == 2; } if (!e && ~f[p][s]) return f[p][s]; int res = 0; int u = e ? bit[p] : 9; for (int i = 0; i <= u; ++i) { res += dfs(p-1, new_s(s, i), e&&i==u); } return e ? res : f[p][s] = res;}int cal(int x) { int idx = 0; while (x) { bit[idx++] = x % 10; x /= 10; } return dfs(idx-1, 0, 1);}int main() { int T, l, r; memset(f, 0xff, sizeof (f)); scanf("%d", &T); while (T--) { scanf("%d %d", &l, &r); printf("%d\n", cal(r) - cal(l-1)); for (int i = 0; i < 10; ++i) { printf("%d ", f[i][3]); } puts(""); } return 0; }

 

自己写的搓代码,但是总归也过了:

View Code
#include 
#include
#include
#include
using namespace std;int dp[15][10][3];/* dp[i][j][0] 表示第i位值为j没有3和8的数有多少个 dp[i][j][1] 表示第i位值为j只含有3的数有多少个 dp[i][j][2] 表示第i位值为j只含有8的数有多少个*/int bit[15], idx;int dfs(int pos, int num, int sta, int full) { if (!full && dp[pos][num][sta] != -1) { return dp[pos][num][sta]; } if (pos == 0) { if (num == 3) return dp[pos][num][sta] = (sta==1); else if (num == 8) return dp[pos][num][sta] = (sta==2); else return dp[pos][num][sta] = (sta==0); } int end = full ? bit[pos-1] : 9; int temp = 0; for (int i = 0; i <= end; ++i) { if (sta == 0) { if (i == 3 || i == 8) continue; temp += dfs(pos-1, i, 0, full && i==end); } else if (sta == 1) { if (i == 8) continue; temp += dfs(pos-1, i, 1, full && i==end); if (num == 3 && i != 3) { temp += dfs(pos-1, i, 0, full && i==end); } } else { if (i == 3) continue; temp += dfs(pos-1, i, 2, full && i==end); if (num == 8 && i != 8) { temp += dfs(pos-1, i, 0, full && i==end); } } } if (!full) dp[pos][num][sta] = temp; return temp;}int cal(int x) { int ret = 0; idx = 0; while (x) { bit[idx++] = x % 10; x /= 10; } for (int i = 0; i <= bit[idx-1]; ++i) { if (i != 8) { ret += dfs(idx-1, i, 1, i==bit[idx-1]); // 枚举最高位 } if (i != 3) { ret += dfs(idx-1, i, 2, i==bit[idx-1]); } } return ret;}int main() { int T, a, b; memset(dp, 0xff, sizeof (dp)); int x; scanf("%d", &T); while (T--) { scanf("%d %d", &a, &b); printf("%d\n", cal(b) - cal(a-1)); } return 0; };

 

转载于:https://www.cnblogs.com/Lyush/archive/2013/03/18/2966817.html

你可能感兴趣的文章
php开启opcache
查看>>
C语言位域
查看>>
Python量化教程 常用函数
查看>>
webpack笔记一 起步
查看>>
使用Mdbg.exe 调试.Net 程序
查看>>
谈开发框架
查看>>
Csharp--Read Csv file to DataTable
查看>>
通过 CLI 管理 Jenkins Server
查看>>
使用json格式的数据进行通信
查看>>
php为图片添加水印
查看>>
Datagrid扩展方法InitEditGrid{支持单元格编辑}
查看>>
Numpy学习50例
查看>>
import renumber.py in pymol
查看>>
ionic ngcordova map 地圖
查看>>
对方法继承的深入学习
查看>>
几个机器学习上的概念
查看>>
hdu1195: Open the Lock
查看>>
软件测试术语
查看>>
兄弟连随笔
查看>>
Vue从入门到实战
查看>>