poj3252(组合数学)

这题虽然说是组合数学但是锻炼数位dp的思想是挺有帮组的的

参考大牛博客:http://hi.baidu.com/lxyzmnwvhokptur/item/33ddd66a3b9c8699c5d24919

比较难理解的一题

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<math.h>
using namespace std;
typedef long long lld;
#define oo 0x3f3f3f3f
#define maxn 100+5
int bit[maxn];
lld C[maxn][maxn];

void GetC()
{
    C[0][0]=1;
    for(int i=1;i<30;i++)
    {
        C[i][0]=C[i][i]=1;
        for(int j=1;j<i;j++)
            C[i][j]=C[i-1][j-1]+C[i-1][j];
    }
}

lld Sum(int x)
{
    int len=0;
    while(x)
    {
        bit[++len]=x%2;
        x/=2;
    }
    lld ans=0;
    //计算小与len的数满足条件的个数
    for(int i=1;i<=len-2;i++)//对下一位进行操作所以要-1,但又是求与长度的数所以在-1,于是就是-2
        for(int j=i/2+1;j<=i;j++)
        ans+=C[i][j];
    int zero=0;
    //计算等于len的数满足条件的个数
    for(int i=len-1;i>=1;i--)
    {
        if(bit[i])
        {
            for(int j=(len+1)/2-(zero+1);j<=i-1;j++)//有多少个0减去多少个0,有0的话排列中0的个数就可以减少
                ans+=C[i-1][j];
        }
        else zero++;
    }
    return ans;
}

int main()
{
    GetC();
	int a,b;
	while(scanf("%d %d",&a,&b)!=EOF)
    {
        cout<<Sum(b+1)-Sum(a)<<endl;
    }
	return 0;
}


你可能感兴趣的:(dp,数学,poj)