URAL 1057. Amount of Degrees
刘聪论文《浅谈数位统计问题》上的例题,是利用图形的方式来方便思考,非常的形象
实现方式有两个,一个是递推版的,一个是非递归版的
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn=32;
int f[maxn][maxn],digit[maxn];
int cal(int n,int K,int B) // 非递归
{
int ret=0,pos=0,pre=0;
for(;n;n/=B) digit[++pos]=n%B;
for(int i=pos;i>=1&&pre<=K;i--)
{
if(digit[i]>1)
{
ret+=f[i][K-pre]; break;
}
if(digit[i]==1)
{
ret+=f[i-1][K-pre];
pre++;
}
if(i==1&&pre==K) ret++;
}
return ret;
}
int dfs(int pos,int pre,int K)
{
if(pos<=0) return pre==K;
if(digit[pos]>=2) return f[pos][K-pre];
int ret=0;
if(digit[pos]==1)
{
ret = f[pos-1][K-pre];
if(pre<K) ret+=dfs(pos-1,pre+1,K);
return ret;
}
else return dfs(pos-1,pre,K);
}
int cal1(int n,int K,int B) // 递归
{
int pos=0;
for(;n;n/=B) digit[++pos]=n%B;
return dfs(pos,0,K);
}
int main()
{
for(int i=0;i<maxn;i++) f[i][0]=1;
for(int i=1;i<maxn;i++)
for(int j=1;j<=i;j++)
f[i][j]=f[i-1][j]+f[i-1][j-1];
int l,r,K,B;
while(scanf("%d%d%d%d",&l,&r,&K,&B)==4)
printf("%d\n",cal(r,K,B)-cal(l-1,K,B)),
printf("%d\n",cal1(r,K,B)-cal1(l-1,K,B));
return 0;
}