POJ 3286 How many 0's?(数位DP)
来源:互联网 发布:link域名可以备案吗 编辑:程序博客网 时间:2024/06/04 18:58
Description
A Benedict monk No.16 writes down the decimal representations of all natural numbers between and including m and n, m ≤ n. How many 0's will he write down?
Input
Input consists of a sequence of lines. Each line contains two unsigned 32-bit integers m and n, m ≤ n. The last line of input has the value of m negative and this line should not be processed.
Output
For each line of input print one line of output with one integer number giving the number of 0's written down by the monk.
Sample Input
10 11100 2000 5001234567890 23456789010 4294967295-1 -1
Sample Output
122929876543043825876150
题意:让你统计区间里0的个数。
分析:数位DP,开始想不好如何记忆化,神牛Alex想了一个机智的做法,因为对于一个32位数来说,
0的个数肯定不会大于32个,所以我们只需要枚举0的个数(1~32)进行数位DP就行了,那么对于这一类问题
都可以这样搞。
#include<cstdio>#include<cstring>#include<algorithm>#include<vector>#include<string>#include<iostream>#include<queue>#include<cmath>#include<map>#include<stack>#include<set>using namespace std;#define REPF( i , a , b ) for ( int i = a ; i <= b ; ++ i )#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )#define CLEAR( a , x ) memset ( a , x , sizeof a )const int INF=0x3f3f3f3f;typedef long long LL;LL a,b;int m;int num[40];LL dp[40][40][2][40];LL dfs(int pos,int have,int first,int flag){ if(have<0) return 0; if(!pos) return have==0; if(!flag&&dp[pos][have][first][m]!=-1) return dp[pos][have][first][m]; int ed=flag?num[pos]:9; LL res=0; for(int i=0;i<=ed;i++) { if(have>0&&!first&&i) res+=dfs(pos-1,have,1,flag&&i==ed); else if(have>0&&first&&!i) res+=dfs(pos-1,have-1,first,flag&&i==ed); else if(have<=0&&first&&!i) res+=dfs(pos-1,have-1,first,flag&&i==ed); else res+=dfs(pos-1,have,first,flag&&i==ed); } if(!flag) dp[pos][have][first][m]=res; return res;}LL solve(LL x){ if(x==0) return 1; if(x<0) return 0; int pos=0; while(x) { num[++pos]=x%10; x/=10; } LL res=0; for(int i=1;i<=32;i++) { m=i; res+=i*dfs(pos,m,0,1);//pos,have,first,flag } return res+1;}int main(){ CLEAR(dp,-1); while(~scanf("%lld%lld",&a,&b)) { if(a<0) break; LL ans=solve(b)-solve(a-1); printf("%lld\n",ans); } return 0;}
顺带AC一下Light OJ 1032想同的思路
A bit is a binary digit, taking a logical value of either 1 or 0 (also referred to as "true" or "false" respectively). And every decimal number has a binary representation which is actually a series of bits. If a bit of a number is 1 and its next bit is also 1 then we can say that the number has a 1 adjacent bit. And you have to find out how many times this scenario occurs for all numbers up to N.
Examples:
Number Binary Adjacent Bits
12 1100 1
15 1111 3
27 11011 2
Input
Input starts with an integer T (≤ 10000), denoting the number of test cases.
Each case contains an integer N (0 ≤ N < 231).
Output
For each test case, print the case number and the summation of all adjacent bits from 0 to N.
Sample Input
Output for Sample Input
7
0
6
15
20
21
22
2147483647
Case 1: 0
Case 2: 2
Case 3: 12
Case 4: 13
Case 5: 13
Case 6: 14
Case 7: 16106127360
#include<cstdio>#include<cstring>#include<algorithm>#include<vector>#include<string>#include<iostream>#include<queue>#include<cmath>#include<map>#include<stack>#include<set>using namespace std;#define REPF( i , a , b ) for ( int i = a ; i <= b ; ++ i )#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )#define CLEAR( a , x ) memset ( a , x , sizeof a )const int INF=0x3f3f3f3f;typedef long long LL;int t,num[60];LL n,m;LL dp[40][2][40][40];LL dfs(int pos,int pre,int have,int flag){ if(have<0) return 0; if(!pos) return have==0; if(!flag&&dp[pos][pre][have][m]!=-1) return dp[pos][pre][have][m]; int ed=flag?num[pos]:1; LL res=0; for(int i=0;i<=ed;i++) { if(have>0&&(i&pre)) res+=dfs(pos-1,i,have-1,flag&&i==ed); else if(have<=0&&(i&&pre)) res+=dfs(pos-1,i,have-1,flag&&i==ed); else res+=dfs(pos-1,i,have,flag&&i==ed); } if(!flag) dp[pos][pre][have][m]=res; return res;}LL solve(LL x){ int pos=0; while(x) { num[++pos]=x%2; x/=2; } LL ans=0; for(int i=1;i<=32;i++) { m=i; ans+=dfs(pos,0,i,1)*i;//pos,pre,have,flag } return ans;}int main(){ int cas=1; scanf("%d",&t); CLEAR(dp,-1); while(t--) { scanf("%lld",&n); LL ans=solve(n); printf("Case %d: %lld\n",cas++,ans); } return 0;}
- poj 3286 How many 0's? (数位DP+ 统计)
- poj 3286 How many 0's? --- 数位dp
- How many 0's? - POJ 3286 数位dp
- POJ 3286 How many 0's?(数位DP)
- POJ 3286 How many 0's? (数位dp)
- POJ 3286 How many 0's?(数位dp)
- POJ - 3286 - How many 0s? 【数位DP】
- poj 3286 How many 0's? 数位dp
- poj 2282 The Counting Problem && poj 3286 How many 0's? (数位dp)
- POJ3286:How many 0's?(数位DP)
- 数位dp poj3286 How many 0's?
- poj3286--How many 0's?(数位dp)
- poj3286 How many 0's? (数位DP)
- uva11038 How Many O's? 数位dp
- Poj 3286 How many 0's? + Bzoj 1833 count 数字计数(数位统计)
- poj 3286 How many 0's?
- POJ 3286How many 0's?
- poj 3286 How many 0's?
- PAT 数据结构 07-排序2. Insert or Merge (25)
- opcache配置
- 每位Android开发人员不容错过的十大实用工具
- N-Queens II 回溯法求八皇后
- C语言中关键字auto、static、register、const、volatile、extern的作用
- POJ 3286 How many 0's?(数位DP)
- NYOJ 519
- 为码农正名——在互联网公司工作啥样子
- pandas重写Q4
- ACM学习计划
- IDEA中导入git步骤
- java学习之旅61--数组_多维数组_练习_矩阵运算
- androidStudio 又添一个新武器 findBugs
- [leetcode-27]Remove Element(C语言)