给定一个数n,问把其拆分成若干个给定数m的次方数
例如,给定m=3,n可拆分为,0(3^0),3(3^1),9(3^2)......
完全背包变形,其中dp[n][k]表示和为n,其中最大的数不超过m^k的组合方法数
dp[n][k]=dp[n][k-1]+dp[n-m^k][k] (n>=m^k)。
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long llt;
llt dp[10010];
int quick_pow(int n,int k)
{
int ans=1;
while(k)
{
if(k&1) ans*=n;
n*=n;
k>>=1;
}
return ans;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
memset(dp,0,sizeof(dp));
int a,b,n;
scanf("%d%d%d",&a,&b,&n);
int max_pack=0;
//quick_pow(b,max_pack)表示能从n中划分出最大的数
while(quick_pow(b,max_pack+1)<=n) max_pack++;
for(int i=0;i<=n;i++) dp[i]=1;
//滚动数组优化
for(int i=1;i<=max_pack;i++)
{
int p=quick_pow(b,i);
for(int j=p;j<=n;j++)
{
dp[j]=dp[j]+dp[j-p];
}
}
printf("%d %lld\n",a,dp[n]);
}
return 0;
}