[AHOI2001]质数和分解 && CF414B Mashmokh and ACM ...dp计算方案数

 P2563 [AHOI2001]质数和分解 

 假设我们已知一个数以下的所有素数,那么很明显这题就变成了一道完全背包问题。因为素数可以重复使用,总和要为n。

设 dp[i]为拼成i的方案数,x为素数。则状态转移

dp[i]+=dp[i-x]

但是还要注意初始条件才能递推

#include <bits/stdc++.h>
using namespace std;
#pragma warning(disable:4996);
#define ll long long
#define	int ll
#define endl "\n"
#define rep(j,b,e) for(int j=b;j<=e;j++)

int T;
const int N = 2e5 + 10;
const int mod = 100003;
int n, m, k, q;

template <class T, class ...Arg>
void inline pln(T t, Arg ...args);//打印一行参数
template<typename T>
void inline pln(vector<T> a, string s = " ");
template<class T, class ...Arg>
void inline  inln(T& t, Arg&...args);//输入一行数据
template<typename T>
void inln(vector<T>& arr, int n) {
	T t = NULL;
	arr.assign(1, t);
	for (int j = 1; j <= n; j++) {
		cin >> t;
		arr.push_back(t);
	}
}

//----------------------------------

vector<int>arr[201];
signed main()
{
#ifndef ONLINE_JUDGE
	//freopen("in.txt", "r", stdin);
	//freopen("out.txt", "w", stdout);
#endif
	rep(k, 2, 200) {
		rep(j, 2, k) {//朴素的素数筛
			int ok = 1;
			rep(i, 2, j - 1) {
				if (j % i == 0)
				{
					ok = 0;
					break;
				}
			}
			if (ok)
				arr[k].push_back(j);
		}
	}

	vector<int>dp(202, 0);
	while (cin >> n) {
		dp.assign(202, 0);
		dp[0] = 1;//边界条件
		for (auto& x : arr[n]) {//遍历素数
			rep(j, x, n)
				dp[j] += dp[j - x];
		}
		pln(dp[n]);
	}
}

//-------------------------------------
void inline  inln() {}
template<class T, class ...Arg>
void inline  inln(T& t, Arg&...args) {
	cin >> t;
	inln(args...);
}
void inline pln() {
	cout << "\n";
}
template <class T, class ...Arg>
void inline pln(T t, Arg ...args) {
	cout << t << " ";
	pln(args...);
}
template<typename T>
void inline pln(vector<T> a, string s) {
	for (T& x : a) {
		cout << x << s;
	}
	cout << endl;
}

CF414B Mashmokh and ACM - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

很容易看出题目有两个状态,数列最大元素和数列长度。

设dp[i][j]为最大元素为i数列长度j的方案数。t为i的因数

状态转移为

dp[i][j]+=dp[t][j-1]

但是因为直接枚举因数会超时,所以试着反过来

 

#include <bits/stdc++.h>
#include<iostream>
#include<thread>
using namespace std;
#pragma warning(disable:4996);
#define ll long long
#define	int ll
#define endl "\n"
#define rep(j,b,e) for(int j=b;j<=e;j++)
#define eb(arr) arr.begin(),arr.end()
#define mm(arr) memset(arr,0,sizeof(arr))
#define get(a,node) get<a-1>(node)
int T;
const int N = 2e5 + 10;
const int mod = 1000000007;
int n, m, k, q;

template <class T, class ...Arg>
void inline pln(T t, Arg ...args);//打印一行参数
template<typename T>
void inline pln(vector<T> a, string s = " ");
template<class T, class ...Arg>
void inline  inln(T& t, Arg&...args);//输入一行数据
//----------------------------------
vector<vector<int>>dp(2010, vector<int>(2021));

struct node {
	int x, y;
};
signed main()
{
#ifndef ONLINE_JUDGE
	//freopen("in.txt", "r", stdin);
	//freopen("out.txt", "w", stdout);
#endif

	inln(n, k);
	for (register int i = 0; i <= n; ++i) {
		dp[1][i] = 1;
	}
	for (int i = 1; i <= k; ++i) {
		for (int j = 1; j <= n; ++j) {
			for (int p = 1; p * j <= n; ++p) {//因数
				dp[i][j] = (dp[i][j] + dp[i - 1][p * j]) % mod;
			}
		}
	}
	int ans = 0;
	for (int i = 1; i <= n; ++i) {//因为题目要求不大于n的方案数,所以枚举之前的相加
		ans = (ans + dp[k][i]) % mod;
	}
	pln(ans);

	return 0;
}

//-------------------------------------
void inline  inln() {}
template<class T, class ...Arg>
void inline  inln(T& t, Arg&...args) {
	cin >> t;
	inln(args...);
}
void inline pln() {
	cout << "\n";
}
template <class T, class ...Arg>
void inline pln(T t, Arg ...args) {
	cout << t << " ";
	pln(args...);
}
template<typename T>
void inline pln(vector<T> a, string s) {
	for (T& x : a) {
		cout << x << s;
	}
	cout << endl;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值