Title: Portal
Meaning of the questions: How many 1 n arranged to meet any two adjacent prime number, output the answer modulo mod ~ ask presence.
1 <= n <= 28, 1 <= mod <= 30000
Thinking: readily occur shaped pressure DP, dp [i] [j] where i is the number of the last to fill a number, j is the number of states currently used, each bit corresponds to a binary number. Number scheme is used when the number of states not fill i j, satisfying the condition.
Then find an array of 2 ^ 28 can not open, can not do, need to find ways to optimize it.
We those classified into the same number have the same quality factor, for example: 2 and 4 and 8 are the same type, type 3 and 9 are the same, however, 3, and 6 are not the same type. 1,171,923 and then classified into the same, because they are relatively prime, and no one. After completion points, a total of up to 15 group, it can open up an array for each number, with different binary representation, see code.
#include <bits/stdc++.h> #define LL long long #define mem(i, j) memset(i, j, sizeof(i)) #define rep(i, j, k) for(int i = j; i <= k; i++) #define dep(i, j, k) for(int i = k; i >= j; i--) #define pb push_back #define make make_pair #define INF INT_MAX #define inf LLONG_MAX #define PI acos(-1) using namespace std; const int N = 2e6 + 5; short dp[19][N]; int c[30], vis[N], statu[30], bs[30], G[30][30]; int n, mod, up; int cnt; int tmp[10] = {2, 3, 5, 7, 11, 13, 17, 19, 23}; int get(int i, int x) { int res = (x % bs[i + 1]) / (bs[i]); return res; } void dfs(int s, int x) { if(s == 0) { dp[x][0] = 1; return ; } if(dp[x][s] != -1) return ; dp[x][s] = 0; rep(i, 1, cnt) { if(G[x][i] && get(i, s) >= 1) { dfs(s - bs[i], i); dp[x][s] = ((int)dp[x][s] + dp[i][s - bs[i]]) % mod; } } } void solve() { scanf("%d %d", &n, &mod); mem(dp, -1); mem(vis, 0); mem(statu, 0); mem(c, 0); mem(G, 0); int ans = 0; cnt = 0; statu[++cnt] = 0; c[cnt] = 1; rep(i, 2, n) { /// 分类 int st = 0; if(i == 17 || i == 19 || i == 23) { c[1]++; continue; } rep(j, 0, 5) { if(i % tmp[j] == 0) { st |= (1 << j); } } if(!vis[st]) { statu[++cnt] = st; c[cnt] = 1; vis[st] = cnt; } elseC [VIS [ST]] ++; } REP (I, . 1 , CNT) REP (J, . 1 , CNT) { /// determines whether coprime IF ((statu [I] & statu [J]) == 0 ) G [I] [J] = . 1 ; } up = 0 ; BS [ . 1 ] = . 1 ; REP (I, . 1 , CNT) { /// each one has its own binary BS [I + . 1 ] BS = [I] * (C [I] + . 1 ); up + BS = [I] * C [I]; } REP (I, . 1 , CNT) { DFS (up - BS [I], I); ANS = (( int ) ANS + DP [I] [up - BS [I]])% MOD; } REP (I, . 1 , CNT) { the while (C [I]> . 1 ) { /// the same class as well as after the first take to get points, to take the c [i] factorial ANS = (( int ) ANS * c [i])% MOD; c [i] - ; } } the printf ( " % D \ n- " , ANS); } int main () { int _; Scanf ( " % D " , & _); the while (_-- ) Solve (); return 0; }