Index of super-prime题意:首先定义一个超级素数,素数是2 3 5.。。 而超级素数是在所有的素数中编号也是素数的,比如3 5 (编号是2, 3),给出一个数n~10000,如果这个数不能只用超级素数的和表示,输出0,如果可以,输出个数最少的情况。
题解:首先筛素数,然后根据素数搞出来超级素数。之后能否达到n,其实就是用已经有的超级素数作为物品,用完全背包去达到n,dp表示最少的个数,额外用from来记录转移过来的状态。
爱61的题解:很大的时候,可以拆成。。。XXX61 + 61XX,一定可以构造成,那么当小于6161时,就要考虑了,很小的时候,先考虑本身就有61的,用这些作为物品来达到n,也是一个完全背包。
重点:将一个数字在一定要求下拆分成满足限制的数字,就是完全背包。注意爱61题目的思维,构造很重要的,然后枚举,然后0背包。
下面的代码是Index of super-prime,并且dp不是习惯的完全背包写的。。。以要达到的数字i为基础,枚举到底最后一个数是加上谁。。。以后直接完全背包就好了= =
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <ctype.h>
#include <limits.h>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#include <stack>
#include <set>
#include <bitset>
#define CLR(a) memset(a, 0, sizeof(a))
#define REP(i, a, b) for(int i = a;i < b;i++)
#define REP_D(i, a, b) for(int i = a;i <= b;i++)
typedef long long ll;
using namespace std;
const int maxn = 1e4 + 1000;
const int INF = INT_MAX/2 - 1;
int vis[maxn], prime[maxn], super_prime[maxn], prime_n, super_prime_n;
int is_super_prime[maxn];
void getSuperPrime()//搞到超级素数
{
prime_n = 0;
CLR(vis);
CLR(is_super_prime);
for(int i = 2; i <= 10000; i++)
{
if(!vis[i])
{
prime[++prime_n] = i;
for(int j = i; j <= 10000; j += i)
{
vis[j] = 1;
}
}
}
super_prime_n = 0;
for(int i = 1; prime[i] <= prime_n; i++)
{
super_prime[++super_prime_n] = prime[prime[i]];
}
for(int i = 1; i <= super_prime_n; i++)
{
is_super_prime[super_prime[i]] = 1;
}
}
int n, num[maxn], first[maxn], ans[maxn];
void getDp()//以后用完全背包
{
num[0] = 0;
for(int i = 1; i <= 10000; i++)
{
int tmp_n = INF, tmp_f;
if(is_super_prime[i])
{
num[i] = 1;
first[i] = i;
continue;
}
for(int j = 1; (super_prime[j] <= i&&j <= super_prime_n); j++)
{
if(num[i - super_prime[j]] + 1 < tmp_n)
{
tmp_n = num[i - super_prime[j]] + 1;
tmp_f = super_prime[j];
}
}
num[i] = tmp_n;
first[i] = tmp_f;
}
}
bool cmp(int a, int b)
{
return a > b;
}
int main()
{
// freopen("4Din.txt", "r", stdin);
//freopen("4Dout.txt", "w", stdout);
getSuperPrime();
getDp();
while(scanf("%d", &n) != EOF)
{
if(num[n] != INF)
{
int ans_n = 0;
int lft;
lft = n;
printf("%d\n", num[n]);
while(lft!=0)
{
ans[ans_n++] = first[lft];
lft -= first[lft];
}
sort(ans, ans + ans_n, cmp);
for(int i = 0;i < ans_n;i++)
{
printf("%d%c", ans[i], (i == ans_n - 1 ? '\n' : ' '));
}
}
else
{
printf("0\n");
}
}
return 0;
}