题目链接:http://poj.org/problem?id=3252
这道题本来一点也不难,思路一开始也是对的,但是就是细节啊,就是自己写代码的能力太差了啊!竟然一而再再二三的wa,然后让我改了一个晚上加上午,看来以后还是要多练习啊!
#include<iostream>
#include<string>
#include<cstdio>
__int64 b[40][40];
void fun()
{
int i,j;//b[i][j]表示i位数中j个0
for(i=1; i<40; i++)
b[0][i]=0;
for(i=0; i<40; i++)
b[i][0]=1;
for(i=1; i<40; i++)
for(j=1; j<=i; j++)
if(i==j)
b[i][j]=1;
else
b[i][j]=b[i-1][j]+b[i-1][j-1];
}
int main()
{
__int64 n,m,i,j,k;
__int64 a[41];
fun();
a[1]=0;
a[0]=0;
j=1;
for(i=2; i<=40; i++)
{
j*=2;
if(i%2==0)//0占一半
a[i]=j/2;
else
a[i]=(j-b[i-1][(i-1)/2])/2;
}
while(scanf("%I64d%I64d",&n,&m)!=EOF)
{
int s[40];
i=0;
int t=0;//n不用带自己内身的
while(n!=0)//i为n转换为二进制后的长度的
{
s[++i]=n%2;
n=n/2;
}
for(j=1; j<=i-1; j++)//先是位数较小的
n+=a[j];
int l=1,o=0;//分别记录1和0的个数
for(j=i-1; j>=1; j--)//还有i-2个需要操作的
if(s[j]==1)
{
o++;
for(k=0; k<=j-1; k++)
{
if(o+k>=l+(j-1-k))//o的个数比l的个数多
{
n+=b[j-1][k];
}
}
o--;
l++;
}
else
o++;
i=0;
while(m!=0)//i为n转换为二进制后的长度的
{
s[++i]=m%2;
if(s[i]==0)
t++;
m=m/2;
}
if((i%2==0 && t>=i/2) || (i%2!=0 && t>i/2))//代表本身的
m++;
for(j=1; j<=i-1; j++)//先是位数较小的
m+=a[j];
l=1;o=0;
for(j=i-1; j>=1; j--)//还有i-2个需要操作的
if(s[j]==1)
{
o++;
for(k=0; k<=j-1; k++)
{
if(o+k>=l+(j-1-k))//o的个数比l的个数多
m+=b[j-1][k];
}
o--;
l++;
}
else
o++;
printf("%I64d\n",m-n);
}
return 0;
}