题目链接:http://cogs.pro:8080/cogs/problem/problem.php?pid=66
题解:
直接枚举复杂度是O(n!*n),原地爆炸。我们考虑优化。
直接枚举过程中可以判断前后是不是素数,进行剪枝,复杂度O(7!)(15以内的素数有7个),可过。
或者我们直接枚举素数,复杂度同上。
注意:第一个数要特判,因为不特判的话只能计算第一个数是素数的方案。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #define LL long long 5 #define RI register int 6 using namespace std; 7 const int INF = 0x7ffffff ; 8 const int N = 15 + 2 ; 9 10 inline int read() { 11 int k = 0 , f = 1 ; char c = getchar() ; 12 for( ; !isdigit(c) ; c = getchar()) 13 if(c == '-') f = -1 ; 14 for( ; isdigit(c) ; c = getchar()) 15 k = k*10 + c-'0' ; 16 return k*f ; 17 } 18 int n, cnt = 0, tot = 0 ; int prime[N], ans[N] ; bool p[N*N], vis[N] ; 19 20 inline void Prime_() { 21 memset(p,0,sizeof(p)) ; 22 for(int i=2;i<=(N<<1);i++) { 23 if(!p[i]) prime[++cnt] = i ; 24 for(int j=1;j<=cnt&&prime[j]*i<=(N<<1);j++) { 25 p[i*prime[j]] = 1 ; 26 if(i%prime[j] == 0) break ; 27 } 28 } 29 // for(int i=1;i<=cnt;i++) printf("%d ",prime[i]) ; 30 } 31 32 void dfs(int now,int pre_prime,int pre_num) { 33 if(now == n+1) { 34 tot ++ ; for(int i=1;i<=n;i++) printf("%d ",ans[i]) ; printf(" ") ; 35 } 36 if(now == 1) { 37 for(int i=1;i<=n;i++) { 38 vis[i] = 1 ; ans[now] = i ; 39 dfs(now+1,0,i) ; vis[i] = 0 ; 40 } 41 return ; 42 } 43 for(int i=1;i<=cnt;i++) { 44 if(prime[i] == pre_prime) continue ; 45 int t = prime[i]-pre_num ; if(vis[t] || t > n || t <= 0) continue ; 46 vis[t] = 1 ; ans[now] = t ; 47 dfs(now+1,prime[i],t) ; 48 vis[t] = 0 ; 49 } 50 } 51 52 inline void init_() { 53 n = read() ; Prime_() ; 54 dfs(1,0,0) ; 55 printf("%d",tot) ; 56 } 57 58 int main() { 59 // freopen("dfs3.in","r",stdin) ; 60 // freopen("dfs3.out","w",stdout) ; 61 init_() ; 62 return 0 ; 63 }