m-ary Partitions

来源:互联网 发布:idea创建web项目ubuntu 编辑:程序博客网 时间:2024/04/20 12:50

 给定一个数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;}