您的位置:首页 > 其它

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即可。

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  dp 数位统计