HDU 4623 Crime (mathematical optimization shaped pressure DP +)

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;

}

 

Guess you like

Origin www.cnblogs.com/Willems/p/12400595.html