数位dp

推荐个数位dp 写的比较好的博客

http://www.darkswordzone.com/?cat=25


http://www.spoj.pl/problems/SORTBIT/

这题是学习上面博客的,贴下,方便以后自己复习

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;
int f[33][33];
void init()
{
    for(int i=0; i<=31; i++) f[i][0]=1;
    for(int i=1; i<=31; i++)
    for(int j=1; j<=i; j++)
       f[i][j]=f[i-1][j]+f[i-1][j-1];
}
int solve(int x,int k)
{
    int ans=0,total=0;
    for(int i=32;i;i--)
    {
        if(i!=32&&(x&(1<<i)))
        {
            total++;
            if(total>k) break;
            x^=(1<<i);
        }
        if((1<<(i-1))<=x)  ans+=f[i-1][k-total];
    }
    if(x+total==k) ans++;
    return ans;
}
int main()
{
    init();
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n,m,k;
        scanf("%d%d%d",&m,&n,&k);
        if(m==0)
        {
            if(k==1){puts("0");continue;}
            m++;
            k--;
        }
        int s=1,tmp=solve(n,s)-solve(m-1,s);
        while(tmp<k)
        {
            k-=tmp;
            s++;
            tmp=solve(n,s)-solve(m-1,s);
        }
        int l=m,r=n,mid;
        while(l<r)
        {
            mid=(l+r)>>1;
            int temp=solve(mid,s)-solve(l-1,s);
            if(temp<k){
                l=mid+1;
                k-=temp;
            }else r=mid;
        }
        printf("%d\n",l);
    }
    return 0;
}


你可能感兴趣的:(数位dp)