【51Nod 1201】 整数划分

Description

将N分为若干个不同整数的和,有多少种不同的划分方式,例如:n = 6,{6} {1,5} {2,4} {1,2,3},共4种。由于数据较大,输出Mod 10^9 + 7的结果即可。

Solution

这是一道非常神奇的DP题,用背包直接做会超时。
不过这个DP方程式其实是我推二维背包的时候不小心打错的时候推出来的。
我们设 f[i][j] 表示用i个数推出j的方案数。
然后 f[i][j]=f[i1][ji]+f[i][ji]
表示可以从i-1的一个状态加进来一个i或者把前面的一个状态全部加上1。
那么答案就等于 f[i][n]
我们考虑一下所有的情况,全部减一个1或者减去一个i都是可以推到0状态的,所以不遗漏。而且从这个状态往前是没有重复的,所以这个是合法的。

Code

#include
#include
#include
#include
#include
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fod(i,a,b) for(i=a;i>=b;i--)
using namespace std;
typedef long long ll;
const int maxn=50007,mo=1e9+7;
ll i,j,k,l,t,n,m,ans;
ll f[321][maxn];
int main(){
    scanf("%d",&n);
    f[0][0]=1;
    fo(i,1,320){
        fo(j,i,n){
            f[i][j]=(f[i][j-i]+f[i-1][j-i])%mo;
        }
    }
    fo(i,1,320)ans=(ans+f[i][n])%mo;
    printf("%lld\n",ans);
}

你可能感兴趣的:(noip,DP,贪心)