POJ 3286 How many 0's?(数位DP)
2015-07-13 19:09
381 查看
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
Sample Output
题意:让你统计区间里0的个数。
分析:数位DP,开始想不好如何记忆化,神牛Alex想了一个机智的做法,因为对于一个32位数来说,
0的个数肯定不会大于32个,所以我们只需要枚举0的个数(1~32)进行数位DP就行了,那么对于这一类问题
都可以这样搞。
顺带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
Each case contains an integer N (0 ≤ N < 231).
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 11 100 200 0 500 1234567890 2345678901 0 4294967295 -1 -1
Sample Output
1 22 92 987654304 3825876150
题意:让你统计区间里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; }
相关文章推荐
- N-Queens II 回溯法求八皇后
- NYOJ 519
- android固定头部和侧边表格实现
- C语言中关键字auto、static、register、const、volatile、extern的作用
- poj 3169 Layout 差分约束
- 每位Android开发人员不容错过的十大实用工具
- PAT 数据结构 07-排序2. Insert or Merge (25)
- 算法导论 第四章:分治法(二)
- 在EO中获取某字段基于表的列名
- python namedtuple
- Scala中中下划线(_)的用法
- 简单加解密
- CPaintDC 、CWindowDC、 CClientDC、 CDC的区别与联系
- 虚函数、虚指针和虚表
- 【leetcode-90】SubsetII(java 语言)
- SQL将汉字转化为拼音(首字母、全拼)
- 报表的制作
- 设计模式
- Volley源码分析
- 饭统崩溃:不创新、权力下放是不是作死