hdu 3555(数位dp入门)
来源:互联网 发布:杂牌液晶电视数据 编辑:程序博客网 时间:2024/04/28 08:02
题意就是求从整数1到N中有多少个含有“49”的数? 比如N=500,那么 "49","149","249","349","449","490","491","492","493","494","495","496","497","498","499",
dp[i][1]=dp[i-1][0]; //在不含49的情况下高位加9
dp[i][2]=dp[i-1][2]*10+dp[i-1][1]; //在含有49的情况下高位随便加一位或者不含49但高位是9,在前面最高位加上4就可以了
so the answer is 15.
先说一下总体思路:
假设统计N=591时,那么按以下的顺序进行统计:
1~499 确定5这一位,统计的数比它小
500~589 确定9这一位 ,统计的数比它小
590 确定1这一位,统计的数比它小
最后判断一下自身是不是符合 即591
循环三次就把符合题意的数的总数全都求出来了,这就是本题的数位DP的奥妙之处.
再比如 1249
1~999
1000~1199
1200~1239
1240~1248
1249
dp[i][j] 表示长度为i的数(也就是有i位数)状态为j的数的总数有多少
本题状态有三种:
①dp[i][0]代表长度为i且不包含49的数有多少个
②dp[i][1]代表长度为i且不包含49且左边第一位(最高位)为9的数有多少个
③dp[i][2]代表长度为i且包含49的数有多少个
打表预处理,0<=i<=21(21位就够了),主要是处理状态的转移
dp[i][0]=dp[i-1][0]*10-dp[i-1][1]; //dp[i][0]高位随便加一个数字都可以,但是会出现49XXX的情况,要减去
对于第i位,说长度为i比较好理解,先加上长度为i-1的所有数中包含49的数,即 ans+=dp[i-1][2]*bit[i]; 为什么乘以bit[i]呢? 比如 bit[i]=5, 那么小于5的数有5种选择,即0,1,2,3,4 ,对于每种选择长度为i-1的数中都有dp[i-1][2]个符合题意的数,所以有 dp[i-1][2]*bit[i] , 所以就求出了第i位比5小的所有数,对于590这个数来说,就是求出了
1~499这些数中一部分有多少符合题意的数。还有i-1位数中如果高位是9,那么第i位只要是4也可以符合题意,所以有了 if(bit[i] >4) ans += dp[i-1][1];
//#pragma comment(linker, "/STACK:1024000000,1024000000")#include<iostream>#include<stdio.h>#include<math.h>#include <string>#include<string.h>#include<map>#include<queue>#include<set>#include<utility>#include<vector>#include<algorithm>#include<stdlib.h>using namespace std;#define eps 1e-8#define pii pair<int,int>#define inf 0x3f3f3f3f#define rd(x) scanf("%d",&x)#define rd2(x,y) scanf("%d%d",&x,&y)#define ll long long int#define mod 1000000007#define maxn 11000#define maxm 10001005int mi(int a,int b){return a<b?a:b;}int ma(int a,int b){return a>b?a:b;}ll dp[21][3];void init(){ dp[0][0]=1; dp[0][1]=dp[0][2]=0; for(int i=1;i<21;i++){ dp[i][0]=10*dp[i-1][0]-dp[i-1][1]; dp[i][1]=dp[i-1][0]; dp[i][2]=dp[i-1][2]*10+dp[i-1][1]; }}int main(){ int t; ll n; rd(t); init(); while(t--){ scanf("%I64d",&n); int len=1; int num[22]; while(n){ num[len++]=n%10; n/=10; } num[len]=0; ll ans=0; bool flag=false; for(int i=len-1;i>=1;i--){ ans+=dp[i-1][2]*num[i]; if(flag) ans+=dp[i-1][0]*num[i]; else if(num[i]>4) ans+=dp[i-1][1]; if(num[i+1]==4&&num[i]==9) flag=true; } if(flag) ans++; printf("%I64d\n",ans); } return 0;}
- hdu 3555(数位dp 入门)
- hdu 3555(数位dp入门)
- HDU 3555 数位DP 入门
- hdu 3555 数位dp入门
- HDU 3555 Bomb 详解(数位DP入门题)
- HDU 3555 数位DP入门(两种思路)
- hdu 3555数位dp基础入门题
- hdu 3555数位DP 入门题
- 数位DP入门之hdu 3555 Bomb
- 数位dp入门题hdu-3555
- HDU-3555 Bomb (数位dp 入门题)
- hdu 3555(数位dp)
- HDU 2089 数位 dp 入门
- hdu 2089 入门数位dp
- HDU 2089 数位DP入门
- hdu 2089 数位dp入门
- hdu 2089 数位dp入门
- hdu 2089 & hdu 3555 (数位DP)
- iOS开发 ----- 上拉加载
- J字首类破解补丁速查
- Kmeans聚类及图像分割
- 2015-9-29
- Spark MLlib之机器学习(一)
- hdu 3555(数位dp入门)
- chrome与12306
- 坑爹流氓网站360.cn
- c++策略模式strategy
- redis学习笔记
- 坑爹流氓天极网yesky.com
- 流氓软件 电脑软件管家
- SpringMVC的处理流程
- Z字首类破解补丁速查