[HNOI2012] Set selection --- Shape pressure DP

[HNOI2012] Collection selection

Topic description

The course "Set Theory and Graph Theory" has an assignment problem, which requires students to find all subsets of \({1,2,3,4,5}\) that satisfy the following conditions: If x is in the subset , then 2x and 3x cannot be in this subset.

The students didn't like this kind of enumeration problem, so they turned it into the following problem: For any positive integer \(n<=100000\),

How to find the number of subsets of \(1,2,3...n\) that satisfy the above constraints (just output the result of modulo \(10^{9}+1\)), now This question is left to you.

 

Input format:

There is only one row with a positive integer n, and 30% of the data satisfy n<=20.

 

Output format:

Contains only a positive integer representing how many subsets of {1, 2,..., n} satisfy the above constraints.

 

Input Example #1:  Copy
4
 
Output Sample #1:  Copy
8

Example explanation
There are 8 sets that meet the requirements, which are empty sets, {1}, {1, 4}, {2}, {2, 3}, {3}, {3, 4}, {4}.
 
A very good question.
Write a line for multiples of 2 and a column for multiples of 3.
For example, the following matrix
\(

\begin{bmatrix}
&1 &2 &4 &8 \;\;\\
&3 &6 &12 &24 \;\;\\
&9 &18 &36 &72 \;\;
\end{bmatrix}

\)
It can be found that the number of elements and columns in a line will not exceed \(\log n\)
Therefore, consider pressing row\column to\(DP\)
 
What if there are no elements involved in this matrix?
Re-create a matrix to\(DP\)
 
Two numbers:
\(\log_{2} n = 18\)
\(\log_{3} n = 11\)
The final complexity is \(O(2^{22}*18)\) (may not be accurate)
 
Notice:
The dimension of the shape pressure must be the dimension that is a multiple of 3, otherwise the complexity will degenerate to \(O(11*2^{36})\) (I like it)
The modulus is \(10^{9}+1\), don't make a mistake (yes, it's me again)
 
#include <cstdio>
#include <cstring>
#include <bitset>
#define mod (100000001)
#define sid 200050
#define ri register int
using namespace std;

inline void up(int &x, int y) {
    x += y; if(x >= mod) x -= mod;
}

inline void mu(int &x, int y) {
    long long tmp = (1ll * x * y) % mod;
    x = (int)tmp;
}

int n;
bitset <100050> flag;
int num[25][25], lim[40], bit[40];
int dp[20][sid], ans = 1;

inline int Solve(int kp) {
    memset(num, 0, sizeof(num));
    num[1][1] = kp; 
    for(ri i = 1; i <= 19; i ++) lim[i] = 0;
    for(ri i = 2; i <= 11; i ++) 
    if(num[1][i - 1] * 3 <= n) num[1][i] = num[1][i - 1] * 3;
    for(ri i = 2; i <= 18; i ++) {
        if(num[i - 1][1] * 2 > n) break;
        num[i][1] = num[i - 1][1] * 2;
        for(ri j = 2; j <= 11; j ++) 
        if(num[i][j - 1] * 3 <= n) num[i][j] = num[i][j - 1] * 3;
    }
    for(ri i = 1; i <= 18; i ++)
    for(ri j = 1; j <= 11; j ++)
    if(num[i][j]) lim[i] |= bit[j - 1], flag[num[i][j]] = 1;
    for(ri i = 1; i <= 19; i ++)
    for(ri j = 0; j <= lim[i]; j ++) dp[i][j] = 0;
    dp[0][0] = 1;
    for(ri i = 1; i <= 19; i ++)
    for(ri j = 0; j <= lim[i - 1]; j ++)
    if(dp[i - 1][j])
    for(ri k = 0; k <= lim[i]; k ++)
    if((k & (k >> 1)) == 0 && (j & k) == 0)
    up(dp[i][k], dp[i - 1][j]);
    return dp[19][0];
}

inline void DP() {
    for(ri i = 0; i <= 27; i ++) bit[i] = 1 << i;
    for(ri i = 1; i <= n; i ++) if(!flag[i]) mu(ans, Solve(i));
    printf("%d\n", ans);
}

int main() {
    scanf("%d", &n);
    DP();
    return 0;
}
sad

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325071251&siteId=291194637