码迷,mamicode.com
首页 > 其他好文 > 详细

900. 整数划分

时间:2020-09-17 17:00:29      阅读:16      评论:0      收藏:0      [点我收藏+]

标签:com   iostream   inf   变换   大致   pac   数字   整数   问题   

完全背包解法:

为什么想到完全背包变式?

因为划分一个整数n,只能用<= n的数字,并且一个数字可以用无限次,所以是类似于完全背包的问题。

技术图片

得到状态转移方程:

\(f(i, j) = f(i - 1, j) + f(i - 1, j - i) + f(i - 1, j - 2 * i) + ... + f(i - 1, j - k * i) + ...\)

朴素写法:大致是\(O(n^3)\)有TLE风险

#include<iostream>
using namespace std;

const int N = 1010, MOD = 1e9 + 7;
int f[N][N];
int n;

int main(){
    cin >> n;
    
    for(int i = 0; i <= n; i ++) f[i][0] = 1;
    
    for(int i = 1; i <= n; i ++)
        for(int j = 1; j <= n; j ++)
            for(int k = 0; k * i <= j; k ++)
                f[i][j] = (f[i][j] + f[i - 1][j - k * i]) % MOD;
                
    cout << f[n][n];
    
    return 0;
}

从状态转移方程角度优化:

\(f(i, j) = f(i - 1, j) + f(i - 1, j - i) + f(i - 1, j - 2 * i) + ... + f(i - 1, j - k * i) + ...\\f(i, j - i) = \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ f(i - 1, j - i) \ \ +f(i - 1, j - 2 * i) + ... + f(i - 1, j - k*i)+...\)

所以\(f(i, j) = f(i - 1, j) + f(i, j - i)\)

#include<iostream>
using namespace std;

const int N = 1010, MOD = 1e9 + 7;
int f[N][N];
int n;

int main(){
    cin >> n;
    
    for(int i = 0; i <= n; i ++) f[i][0] = 1;
    
    for(int i = 1; i <= n; i ++)
        for(int j = 1; j <= n; j ++){
            f[i][j] = f[i - 1][j];
            if(j >= i)
                f[i][j] = (f[i][j] + f[i][j - i]) % MOD;
        }
                
    cout << f[n][n];
    
    return 0;
}

等价变换代码

#include<iostream>
using namespace std;

const int N = 1010, MOD = 1e9 + 7;
int f[N];
int n;

int main(){
    cin >> n;
    
    f[0] = 1;
    
    for(int i = 1; i <= n; i ++)
        for(int j = i; j <= n; j ++)
            f[j] = (f[j] + f[j - i]) % MOD;
        
    cout << f[n];
    
    return 0;
}

另一个dp解法

技术图片

初始条件: f(0, 0) = 1

#include<iostream>
using namespace std;

const int N = 1010, MOD = 1e9 + 7;
int f[N][N];
int n;

int main(){
    cin >> n;
    
    f[0][0] = 1;

    for(int i = 1; i <= n; i ++)
        for(int j = 1; j <= i; j ++)
            f[i][j] = (f[i - 1][j - 1] + f[i - j][j]) % MOD;
                
    int res = 0;
    
    for(int i = 0; i <= n; i ++) res = (res + f[n][i]) % MOD;
    
    cout << res;
    
    return 0;
}

900. 整数划分

标签:com   iostream   inf   变换   大致   pac   数字   整数   问题   

原文地址:https://www.cnblogs.com/tomori/p/13625344.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!