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 __int64 LL 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; }
#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); } else ans += 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); else ans += 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; }