数位DP练习
Posted liylho
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数位DP练习相关的知识,希望对你有一定的参考价值。
水题
发布时间: 2017年6月22日 19:15 最后更新: 2017年6月23日 20:10 时间限制: 1000ms 内存限制: 128M
给一个数n,求0~n内有多少个数满足其二进制形式不存在相邻的1
比如 0,1,2是可以的,3不可以。
多组输入,每组输入一个数。
输出答案,
复制
0
1
数位DP
代码1:
1 #include<stdio.h> 2 #include<iostream> 3 #include<algorithm> 4 #include<string.h> 5 #include<math.h> 6 #include<stdlib.h> 7 #include<ctype.h> 8 #include<stack> 9 #include<queue> 10 #include<map> 11 #include<set> 12 #include<vector> 13 #define ll long long 14 #define db double 15 using namespace std; 16 const int N=1e6+5; 17 const int mod=1e9+7; 18 int n; 19 ll dp[64][2][2]; 20 int a[100]; 21 ll dfs(int p,int pre,int st,int lim){//统计存在相邻1的数字 22 if(p==-1) return st==1; 23 if(!lim&&dp[p][pre][st]!=-1) return dp[p][pre][st]; 24 ll ans=0; 25 int up=lim?a[p]:1; 26 for(int i=0;i<=up;i++){ 27 int nst=st; 28 if(i&&pre) nst=1; 29 ans+=dfs(p-1,i,nst,lim&&i==a[p]); 30 } 31 if(!lim) dp[p][pre][st]=ans; 32 return ans; 33 } 34 void f(int n){ 35 int k=n; 36 memset(dp,-1, sizeof(dp)); 37 memset(a,0, sizeof(a)); 38 int cnt=0; 39 while(n){ 40 a[cnt++]=n%2; 41 n/=2; 42 } 43 printf("%lld\n",k+1-dfs(cnt-1,0,0,1)); 44 } 45 int main(){ 46 while(scanf("%d",&n)==1){ 47 f(n); 48 } 49 }
标程:
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N = 1e5+5; 4 typedef long long ll; 5 6 ll dp[N][2]; 7 int a[N]; 8 9 ll dfs(int p,int pre,bool lim)//统计不存在相邻1的数字个数 10 { 11 if(pos == -1) return 1; 12 if(!lim && dp[p][pre] != -1) 13 return dp[p][pre]; 14 int up = lim ? a[p] : 1; 15 ll ans = 0; 16 for(int i =0;i<=up;i++) 17 { 18 if(pre&& i) continue; 19 ans += dfs(p-1,i,lim&&i==a[p]); 20 } 21 if(!lim) dp[p][pre] = ans; 22 return ans; 23 } 24 ll solve(ll n) 25 { 26 memset(dp,-1,sizeof(dp)); 27 memset(a,0,sizeof(a)); 28 int cnt = 0; 29 while(n) 30 { 31 a[cnt++] = n % 2; 32 n /= 2; 33 } 34 return dfs(cnt-1,0,1); 35 } 36 int main() 37 { 38 ll n; 39 while(cin >> n) 40 { 41 cout << solve(n) << endl; 42 } 43 }
以上是关于数位DP练习的主要内容,如果未能解决你的问题,请参考以下文章