[AcWing 900] 整数划分

image

类比完全背包 复杂度 O(n2)

总体复杂度 10002=1×106


点击查看代码
#include<iostream>

using namespace std;
const int N = 1010, mod = 1e9 + 7;
int n;
int f[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] << endl;
	return 0;
}

  1. 状态表示
    f[i][j] 表示从数字 1 ~ i 中选,且总和等于 j 的选法数量
  2. 状态转移
    类比完全背包的优化方式
    f[i][j]=f[i1][j]+f[i1][ji]+f[i1][j2i]+
    f[i][ji]=f[i1][ji]+f[i1][j2i]+
    可以得到 f[i][j]=f[i1][j]+f[i][ji]

另一种思考方式 复杂度同上


点击查看代码
#include<iostream>

using namespace std;
const int N = 1010, mod = 1e9 + 7;
int n;
int f[N][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 = 1; i <= n; i ++)	res = (res + f[n][i]) % mod;
	cout << res << endl; 
	return 0;
}

  1. 状态表示
    f[i][j] 表示总和是 i ,并且分成 j 个数的方案数量
  2. 状态转移
    f[i][j] 分为两种情况:
    ① 分成的数中最小的数为 1 ,可以把 1 单独拿出来,等价于 f[i1][j1]
    ② 分成的数中最小的数大于 1 ,可以把所有分成的数都减去 1 ,总和减去 j ,等价于 f[ij][j]
    状态转移方程为:f[i][j]=f[i1][j1]+f[ij][j]
  3. 结果
    要求的是总和为 n 的方案数量,可以分成 1,2,3,,n 个数,总的方案数是这些不同分法方案个数之和
posted @   wKingYu  阅读(24)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
欢迎阅读『[AcWing 900] 整数划分』
点击右上角即可分享
微信分享提示