P2563 [AHOI2001]质数和分解
假设我们已知一个数以下的所有素数,那么很明显这题就变成了一道完全背包问题。因为素数可以重复使用,总和要为n。
设 dp[i]为拼成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的因数
状态转移为
但是因为直接枚举因数会超时,所以试着反过来
#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;
}