poj 3252 Round Numbers 数位DP or 组合数学

来源:互联网 发布:ubuntu textinfo 编辑:程序博客网 时间:2024/04/30 09:32

POJ 3252

题意 : 给你两个数  a  < b ,a到b的二级制中 0 的个数大于 1 的个数 的数有多少个


数位DP :刚开始这样搞得,dp[i][j],i代表第几个数  j代表可以弄几个0 ,被雷到了,就是搞不出,各种烦
,后来改成dp[i][j][k],i代表几位,j代表前面有j个1,k代表前面有k个0


组合数学 :首先对一个二进制有num位的数,首先处理出有num位的有多少个,然后处理出小于num位的数


组合数学code

#include <stdio.h>#include <string.h>#define max(a,b) (a>b?a:b)#define LL __int64LL c[88][88] ;int a[66];LL solve(LL x){if(x == 0)return 0;int cnt[2] , i, j , num = 0;LL ans = 0;while(x){a[++num] = x%2;x /= 2;}cnt[0] = cnt[1] = 0;for(i = 1;i <= num; i++)cnt[a[i]]++;if(cnt[0]>=cnt[1])ans++;for(i = 1;i< num; i++){if(a[i] == 0)continue;cnt[0] = cnt[1] = 0;for(j = num;j > i; j--)cnt[a[j]]++;cnt[0]++;int m = (num+1)/2-cnt[0];m = max(m,0);for(j = m;j < i;j ++){if(c[i-1][j]==0)printf("%d %d\n",i,j);ans += c[i-1][j];}}for(i = num-1;i >= 1;i --){for(j = (i+1)/2;j < i; j++)ans += c[i-1][j];}return ans;}int main(){int i,j;LL x,y;memset(c,0,sizeof(c));c[0][0] = 1;for(i = 1;i <= 66; i++)for(j = 0;j <= 66; j++){c[i][j] = c[i-1][j] + c[i-1][j-1];}scanf("%I64d%I64d", &x, &y) ;LL ans1 = solve(x-1);LL ans2 = solve(y);printf("%I64d\n",ans2-ans1);return 0;}

数位DP code

#include <stdio.h>#include <string.h>int dp[66][66][66],a[66] ;void init(){memset(dp,-1,sizeof(dp));}int dfs(int len,int num1,int num0,int doing,int first){if(len==0){if(first)return 1;if(num0>=num1)return 1;return 0;}if(!doing && !first && dp[len][num1][num0]!=-1)return dp[len][num1][num0];int end = doing ? a[len] : 1;int ans = 0;for(int i = 0;i <= end; i++){if(first){if(i==0){ans += dfs(len-1,0,0,doing && end==i,1);}elseans += dfs(len-1,num1+1,num0,doing && end==i,0);}else{if(i==0)ans += dfs(len-1,num1,num0+1,doing && i==end,0);elseans += dfs(len-1,num1+1,num0,doing && i==end,0);}}if(!doing && !first)dp[len][num1][num0] = ans;return ans;}int solve(int x){int num = 1;while(x){a[num++] = x%2;x /= 2;}num--;//puts("fuck");int ans = dfs(num,0,0,1,1);return ans;}int main(){init();int x,y;scanf("%d%d", &x, &y);x--;int ans1 = solve(x);int ans2 = solve(y);//printf("%d %d\n" ,ans1,ans2);printf("%d\n", ans2-ans1);return 0;}


原创粉丝点击