poj 3252 Round Numbers (数位DP)
2013-10-19 22:41
405 查看
题意:给你两个十进制数n,m,求n,m在二进制情况下(n,m)区间中数字0比数字1个数多的二进制数有多少个。
思路:数位DP。
设DP[a][b][c]a位数,开头为b,含有c个1的数的个数。
转移方程:
if(b==1)
{
dp[a][b][c]+=dp[a-1][z][c-1] (0<=z<=1,0=<c<=a)
}
else
{
dp[a][b][c]+=dp[a-1][z][c] (0<=z<=1,0<=c<=a)
}
预处理完DP的值,从高到底依次询问比n小的符合要求的数,但是对长度<n 的数字,因为前面有前导0,所以特殊处理,这样算出[0,n),[0,m)的值,则[n,m)=(0,m)-(0,n),最后在特判m即可。
思路:数位DP。
设DP[a][b][c]a位数,开头为b,含有c个1的数的个数。
转移方程:
if(b==1)
{
dp[a][b][c]+=dp[a-1][z][c-1] (0<=z<=1,0=<c<=a)
}
else
{
dp[a][b][c]+=dp[a-1][z][c] (0<=z<=1,0<=c<=a)
}
预处理完DP的值,从高到底依次询问比n小的符合要求的数,但是对长度<n 的数字,因为前面有前导0,所以特殊处理,这样算出[0,n),[0,m)的值,则[n,m)=(0,m)-(0,n),最后在特判m即可。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #define LL long long using namespace std; LL dp[500][2][500]; int len[2]; int num[2][500]; LL n,m; void work() { dp[0][0][0]=1; //dp[1][0][0]=1; for(int i=1; i<=300; i++) { for(int j=0; j<2; j++) { for(int k=0; k<=i; k++) { for(int z=0; z<2; z++) { if(j==1) { dp[i][j][k]+=dp[i-1][z][k-1]; } else { dp[i][j][k]+=dp[i-1][z][k]; } } } } } } void cal(int t)//进制转换 { len[t]=0; if(t==0) { while(n) { num[t][++len[t]]=n%2; n/=2; } } else { while(m) { num[t][++len[t]]=m%2; m/=2; } } } LL solve() { LL res=0; LL sum=0; int m=len[0]>>1;//1的最大个数最大到长度的一半。 for(int i=len[0]; i>0; i--) { if(i!=len[0])//特判长度<len 的 { for(int j=0; j<num[0][i]; j++) { for(int k=0; k<=(m-sum); k++) { res+=dp[i][j][k]; } } } if(num[0][i]==1) sum++; if(sum>m) break; } for(int i=1;i<len[0];i++) { int m=i>>1; for(int j=0;j<=m;j++) { res+=dp[i][1][j]; } } LL res1=0; LL sum1=0; m=len[1]>>1; // printf("%d\n",num[1][2]); for(int i=len[1]; i>0; i--) { if(i!=len[1]) { for(int j=0; j<num[1][i]; j++) { for(int k=0; k<=(m-sum1); k++) { // cout<<j<<endl; res1+=dp[i][j][k]; } } } if(num[1][i]==1) sum1++; if(sum1>m) break; } for(int i=1;i<len[1];i++) { int m=i>>1; for(int j=0;j<=m;j++) { res1+=dp[i][1][j]; } } // printf("%I64d\n",res1); return res1-res; } int check() { int tmp=0; int mm=len[1]>>1; for(int i=len[1]; i>0; i--) { if(num[1][i]==1) tmp++; } if(tmp>mm) return 0; else return 1; } int main() { // freopen("in.txt","r",stdin); memset(dp,0,sizeof(dp)); work(); // printf("%I64d\n",dp[2][0][0]); while(~scanf("%I64d%I64d",&n,&m)) { cal(0); cal(1); printf("%I64d\n",solve()+check()); } return 0; }
相关文章推荐
- poj 3252 Round Numbers (数位DP)
- POJ 3252 Round Numbers(数位DP)
- poj 3252 Round Numbers(数位dp)
- poj 3252 Round Numbers 数位dp
- Round Numbers - POJ 3252 数位dp
- POJ 3252 Round Numbers(数位dp)
- POJ 3252 Round Numbers (数位dp)
- POJ 3252 Round Numbers 数位dp
- poj 3252 Round Numbers(数位DP)
- POJ 3252 Round Numbers [数位DP]【动态规划】
- POJ - 3252 : Round Numbers (数位dp)
- poj 3252 Round Numbers(数位DP,4级)
- 数位DP-POJ-3252-Round Numbers
- POJ - 3252 Round Numbers (数位dp&位运算)
- poj 3252 Round Numbers(数位DP,4级)
- POJ 3252 Round Numbers 数位DP
- POJ 3252 Round Numbers 数位dp(入门
- POJ 3252 Round Numbers (数位DP入门)
- poj3252——Round Numbers(数位dp)
- POJ 3252 - Round Numbers(数位dp)