数位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练习的主要内容,如果未能解决你的问题,请参考以下文章

kotlin-从一个片段更改多个片段的小数位

夜深人静写算法(二十九)- 数位DP

数位dp小练

动态规划_计数类dp_数位统计dp_状态压缩dp_树形dp_记忆化搜索

数位DP

数位dp