HDU3652 B-number 数位DP
来源:互联网 发布:淘宝网店话费充值 编辑:程序博客网 时间:2024/05/09 07:33
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3652
题目大意:统计区间[1,n](n<=1e9)内有多少个含有“13”且能被13整除的数。
分析:数位DP,详解见代码。
实现代码如下:
#include <cstdio>#include <cstring>using namespace std;int dp[15][15][3]; //dp[pos][mod][v]:pos纪录位数,mod纪录余数,v状态标记:0表示当前末尾不为1;1表示当前末尾是1;2表示可以为13整除int dig[15],len;void count(int x){//将x从右到左存储到dig[]中,len纪录位数 len=0; while(x) { dig[++len]=x%10; x/=10; }}int update(int v,int i){ //更新状态标记的取值 int cnt=v; if(v==0&&i==1) //末尾不是1,现在加入的是1 cnt=1; //标记末尾为1 if(v==1&&i!=1) //末尾是1,现在加入的不是1 cnt=0; //标记末尾为0 if(v==1&&i==3) //末尾是1且加入的是3 cnt=2; //标记末尾是13 return cnt;}int dfs(int pos,int mod,int v,int lim) //lim纪录是否为上限(即是否为9){ if(pos<=0) return mod==0&&v==2; //pos<=0表示处理完所有的位 if(!lim && dp[pos][mod][v]!=-1) return dp[pos][mod][v]; int num=lim?dig[pos]:9; //lim为上限,表示当前位i和n的当前位相同,那么i+1位要在[0,num]中取值,否则,i+1位可以在[0,9]取值 int ans=0; for(int i=0;i<=num;i++) ans+=dfs(pos-1,(mod*10+i)%13,update(v,i),lim&&i==num); //lim&&i==num:在最开始,num取出的最高位,所以如果i比num小,那么下一位可以取到[0,9],否则,下一位只能取到[ 0,dig[pos-1] ] if(!lim) dp[pos][mod][v]=ans; return ans;}int main(){ int n; while(scanf("%d",&n)!=-1) { count(n); memset(dp,-1,sizeof(dp)); //初始化 printf("%d\n",dfs(len,0,0,1)); } return 0;}
1 0
- 【数位DP】 hdu3652 B-number
- 【hdu3652】【数位DP】B-number
- 【数位DP】B-number HDU3652
- HDU3652:B-number(数位DP)
- hdu3652 B-number (数位DP)
- HDU3652 B-number 数位DP
- hdu3652 B-number 数位dp
- [HDU3652]B-number && 数位DP
- hdu3652 B-number 数位dp
- hdu3652---B-number(数位dp)
- HDU3652 B-number 数位DP
- hdu3652 B-number 数位dp
- hdu3652 B-number 数位dp
- HDU3652 B-number(数位DP)
- 数位dp--hdu3652 B-number
- hdu3652 B-number(数位DP)
- HDU3652 B-number 数位DP
- hdu3652 B-number 数位dp
- hook
- Cocos2d-x 3.x RenderTexture渲染纹理源码分析
- Wayland与Weston简介
- html的<!DOCTYPE>标签初窥
- HDU 1495 非常可乐
- HDU3652 B-number 数位DP
- 洛谷1119灾后重建(floyd)
- HTML学习4:常用标签之列表标签
- position和anchorPoint
- Windows删除语言栏多余的输入法
- 【好工具分享】时间管理利器——今目标
- C++中虚函数表的介绍
- ios tableview
- 151017下午测试的总结