数位DP入门Ural1057

CF一战让我觉得很疲倦,所以今天感觉很慢。

昨天解D题时候,因为太累,根本连题目都没看,今天看了之后感觉不会做,听闻是数位DP问题。

有某神说过,DP的功力建立在刷过的题上,我真的毫无功力可言。

介绍大家一个很不错的文章。

中学生写的啊!瞬间觉得自己弱爆了……

http://wenku.baidu.com/link?url=q4atTAoZVGlV6sfo0fhED06ogbktY38_TZkGWLkuOpTRiqyI-eDyarkTeL10fv2GdUe53DMIloZ_sD0gZF6xK1ljbcJH1NlLgdyh4aVcGXi

完全根据文章所说的写,毫无问题,一次AC……

/*******************************************************************************/
/* OS           : 3.2.0-58-generic #88-Ubuntu SMP Tue Dec 3 UTC 2013 GNU/Linux
 * Compiler     : g++ (GCC)  4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5)
 * Encoding     : UTF8
 * Date         : 2014-04-07
 * All Rights Reserved by yaolong.
*****************************************************************************/
/* Description: ***************************************************************
*****************************************************************************/
/* Analysis: ******************************************************************
*****************************************************************************/
/*****************************************************************************/

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
long long dp[40][40];
long a[33];
void init(){
  dp[0][0]=1 ;//dp[i][j],表示i位,j个1的数的个数,dp[i][j]=dp[i-1][j]+dp[i-1][j-1] 即第i位为1,第i位为0两种情况
  for(long i=1;i<=31;i++){
     dp[i][0]=dp[i-1][0];   //0个1的情况,等于第i位不是0的即dp[i-1][0].
     for(long j=1;j<=i;j++){
        dp[i][j]=dp[i-1][j]+dp[i-1][j-1];
     }
  }
}
long cal(long x,long k){
   long cnt=0,ans=0;
   for(long i=31;i>0;i--){ //高位开始运算
       if(x&(1<<i)){
           cnt++;
           if(cnt>k) break;
           x=x^(1<<i); //抹掉x的目前最高位


       }
       if((1<<(i-1))<=x){
          ans+=dp[i-1][k-cnt];
       }
   }
   if(cnt+x==k) ans++;   //本身
   return ans;

}
long turn(long n,long B){
   long i=0,j,res=0;
   while(n){
     a[++i]=n%B;  //从1开始末位
     n/=B;
   }
   j=i; //最高位
   while(a[i]<=1){ //高位递减
      i--;
   }
   while(i>=1){ //将右边全部赋值为1
     a[i]=1;
     i--;
   }

   while(j>=1){
     res=a[j]+(res<<1);
     j--;

   }

   return res;


}
long fun(long n,long k,long b){

    long X=turn(n,b);
    return cal(X,k);

}
int main(){

    long X,Y,K,B;
    long res;
    init();
    while(cin>>X>>Y>>K>>B){
      res=fun(Y,K,B)-fun(X-1,K,B);
      cout<<res<<endl;

    }




    return 0;

}




你可能感兴趣的:(入门)