概述
题目链接:
http://poj.org/problem?id=3252分析:
求出S~F中转换成二进制数后0的个数≥1的个数的数字的个数。0的个数大于1的个数的数可以用组合数来做。题解:
- 算出1~F+1和1~S的满足条件的个数相减即可。
- 先一个数转换乘二进制形式存入数组中:
void change(int n)
{
number[0]=0; //nubmer[0]用来存储二进制数总长度
while(n)
{
number[++number[0]]=n%2;//逆序存储二进制数
n/=2;
}
return;
}
然后先将长度小于number[0]的所有满足条件的数算出,这个非常简单,就是满足C(≥(len/2), len)(从len个数中挑≥(len/2)个)的所有数就是题意。
再将number[0]长度下满足条件的数计算出来,从最高位往下搜索即可:
int round(int n)
{
int i,j;
int sum=0; //比十进制数n小的所有RN数
change(n);
//cout << number[0] << endl;
/*计算长度小于number[0]的所有二进制数中RN的个数*/
for(i=1;i<number[0]-1;i++)
for(j=i/2+1;j<=i;j++)
sum += dp[i][j];
/*计算长度等于number[0]的所有二进制数中RN的个数*/
int zero=0; //从高位向低位搜索过程中出现0的位的个数
for(i=number[0]-1;i>=1;i--)
if(number[i]) //当前位为1
for(j=(number[0]+1)/2-(zero+1);j<=i-1;j++)//前面已经出现zero个0了,所以需要减去它
sum+=dp[i-1][j];
else
zero++;
return sum;
}
- AC代码:
#include<iostream>
using namespace std;
int dp[33][33]={0};
int f[33][33];
int number[35];
void init()
{
for(int i=0;i<=32;i++)
for(int j=0;j<=i;j++)
{
if(!j || i==j)
dp[i][j] = 1;
else
dp[i][j] = dp[i-1][j-1] + dp[i-1][j];
//cout << i << " " << j << ": " << dp[i][j] << endl;
}
return;
}
/*十进制n转换二进制,逆序存放到number[]*/
void change(int n)
{
number[0]=0;
while(n)
{
number[++number[0]]=n%2;
n/=2;
}
return;
}
/*计算比十进制数n小的所有RN数*/
int round(int n)
{
int i,j;
int sum=0; //比十进制数n小的所有RN数
change(n);
//cout << number[0] << endl;
/*计算长度小于number[0]的所有二进制数中RN的个数*/
for(i=1;i<number[0]-1;i++)
for(j=i/2+1;j<=i;j++)
sum += dp[i][j];
/*计算长度等于number[0]的所有二进制数中RN的个数*/
int zero=0; //从高位向低位搜索过程中出现0的位的个数
for(i=number[0]-1;i>=1;i--)
if(number[i]) //当前位为1
for(j=(number[0]+1)/2-(zero+1);j<=i-1;j++)
sum+=dp[i-1][j];
else
zero++;
return sum;
}
int main()
{
init();
int a,b;
cin>>a>>b;
cout<<round(b+1)-round(a)<<endl;
return 0;
}
最后
以上就是完美荷花为你收集整理的数位DP(组合数打表)—— Round Numbers ( POJ 3252 )的全部内容,希望文章能够帮你解决数位DP(组合数打表)—— Round Numbers ( POJ 3252 )所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复