首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

HDU 3271 SNIBB (数位统计+2分)

2012-08-27 
HDU 3271 SNIBB (数位统计+二分)转载请注明出处,谢谢 http://blog.csdn.net/ACM_cxlove?viewmodecontents

HDU 3271 SNIBB (数位统计+二分)

转载请注明出处,谢谢 http://blog.csdn.net/ACM_cxlove?viewmode=contents           by---cxlove

题目:将一个数转化成B进制后,他的val表示的是各位上的数字和。详见题目描述。。。。

http://acm.hdu.edu.cn/showproblem.php?pid=3271

首先还是预处理,dp[i][j]表示转化成B进制后,长度为i的数中,数字和为j的数字有多少个,感觉越来越像数位DP。。。

对于询问1:压根就是数位DP,从高位开始枚举,记录之前已经出现的位数和,然后枚举当前位。注意区间的开闭问题,边界处理好

对于询问2:首先通过询问1得出的数目,判断是否存在第K大,然后就是二分答案,判断[l,mid]中和为m的数有多少个。

#include<iostream>#include<cstring>#include<queue>#include<cstdio>#include<cmath>#include<algorithm>#define N 30#define inf 1<<29#define MOD 2007#define LL long longusing namespace std;int dp[32][305];//转换成B进制后,长度为i的数中各位和为j的个数void Init(int b,int m){    memset(dp,0,sizeof(dp));    dp[0][0]=1;    for(int i=1;i<32;i++)        for(int j=0;j<=m;j++)            for(int k=0;k<b&&k+j<=m;k++)                dp[i][j+k]+=dp[i-1][j];}//统计[0,n]中转换成b进制,和为m的个数int clac(int n,int b,int m){    int bit[35],len=0,t=n;    while(t){        bit[++len]=t%b;        t/=b;    }    int sum=0,tot=0;    for(int i=len;i;i--){        for(int j=0;j<bit[i]&&m-tot-j>=0;j++)            sum+=dp[i-1][m-tot-j];        tot+=bit[i];        if(tot>m) break;    }    //本身的和就是m,注意别落下    if(tot==m) sum++;    return sum;}int main(){    int cas=0,kind,x,y,b,m,k;    while(scanf("%d%d%d%d%d",&kind,&x,&y,&b,&m)!=EOF){        Init(b,m);        if(x>y) swap(x,y);        printf("Case %d:\n",++cas);        int cnt=clac(y,b,m)-clac(x-1,b,m);        if(kind==1){            printf("%d\n",cnt);            continue;        }        scanf("%d",&k);        if(k>cnt){            puts("Could not find the Number!");            continue;        }        int low=x,high=y,mid;        while(low<high){            //二分答案,判断在[l,mid]中和为m的个数            mid=(int)((((LL)low+(LL)high))/2);            int now=clac(mid,b,m)-clac(x-1,b,m);            if(now<k)                low=mid+1;            else                high=mid;        }        printf("%d\n",low);    }    return 0;}


热点排行