[HNOI2012]集合选数

Description

《集合论与图论》这门课程有一道作业题,要求同学们求出{1, 2, 3, 4, 5}的所有满足以 下条件的子集:若 x 在该子集中,则 2x 和 3x 不能在该子集中。同学们不喜欢这种具有枚举性 质的题目,于是把它变成了以下问题:对于任意一个正整数 n≤100000,如何求出{1, 2,..., n} 的满足上述约束条件的子集的个数(只需输出对 1,000,000,001 取模的结果),现在这个问题就 交给你了。

Input

只有一行,其中有一个正整数 n,30%的数据满足 n≤20。

Output

仅包含一个正整数,表示{1, 2,..., n}有多少个满足上述约束条件 的子集。

Sample Input

4

Sample Output

8

【样例解释】

有8 个集合满足要求,分别是空集,{1},{1,4},{2},{2,3},{3},{3,4},{4}。

题解:

这题的思路蛮有趣的。 
我们不妨写出来一个矩阵。


\


1


2


3


4


5


1


1


3


9


27


81


2


2


6


18


54


162


3


4


12


36


108


324


4


8


24


72


216


648


5


16


48


144


432


1296

该矩阵的每一个元素的右面的元素都是他的3倍,每一个元素的下面的元素都是他的2倍。 
也就是说,如果我们选出的数在该矩阵中是不相邻的话,那么选出的一定是一个符合题意的子集。 
因为n≤100000,所以该矩阵的行和列一定都很小,最多大概是在17。 
所以我们可以考虑在这个矩阵上状压每一行,然后统计一下该矩阵可取的方案数即可。 
但是我们发现,5,7这种数并没有出现在该矩阵中。 
所以这种矩阵可能有多个,在找完1为左上角的该类型矩阵后,我们只需要寻找1~n中的下一个没有出现在矩阵中的元素充当左上角,再次计算即可。 
由于不同矩阵中的元素互不影响,所以我们需要把所有可能的矩阵的方案数利用乘法原理乘在一起即可。

 1 //Never forget why you start
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cstdlib>
 5 #include<cstring>
 6 #include<cmath>
 7 #include<algorithm>
 8 #define mod (1000000001)
 9 using namespace std;
10 typedef long long lol;
11 lol n,m,map[21][21],vis[100005],ans=1,cnt[21],t[21],f[21][5005];
12 lol dp(lol x) {
13     lol i,j,k;
14     map[1][1]=x;
15     for(i=2; i<=20; i++)
16         if(map[i-1][1]*2<=n)map[i][1]=map[i-1][1]*2;
17         else map[i][1]=n+1;
18     for(i=1; i<=20; i++)
19         for(j=2; j<=20; j++)
20             if(map[i][j-1]*3<=n)map[i][j]=map[i][j-1]*3;
21             else map[i][j]=n+1;
22     for(i=1; i<=20; i++) {
23         cnt[i]=0;
24         for(j=1; j<=20; j++) {
25             vis[map[i][j]]=1;
26             if(map[i][j]<=n)cnt[i]+=t[j];
27         }
28     }
29     for(i=1; i<=20; i++)
30         for(j=0; j<=cnt[i]; j++)
31             f[i][j]=0;
32     f[0][0]=1;
33     for(i=0; i<=20; i++)
34         for(j=0; j<=cnt[i]; j++)
35             if(f[i][j])
36                 for(k=0; k<=cnt[i+1]; k++)
37                     if(!(j&k)&&(!(k&(k<<1))))
38                         f[i+1][k]=(f[i+1][k]+f[i][j])%mod;
39     return f[20][0];
40 }
41 int main() {
42     lol i,j;
43     scanf("%lld",&n);
44     for(i=1; i<=20; i++)t[i]=1<<(i-1);
45     for(i=1; i<=n; i++)
46         if(!vis[i])
47             ans=(ans*dp(i))%mod;
48     printf("%lld\n",ans);
49     return 0;
50 }

原文地址:https://www.cnblogs.com/huangdalaofighting/p/8260278.html

时间: 2024-10-14 11:29:43

[HNOI2012]集合选数的相关文章

bzoj 2734: [HNOI2012]集合选数 状压DP

2734: [HNOI2012]集合选数 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 560  Solved: 321[Submit][Status] Description <集合论与图论>这门课程有一道作业题,要求同学们求出{1, 2, 3, 4, 5}的所有满足以 下条件的子集:若 x 在该子集中,则 2x 和 3x 不能在该子集中.同学们不喜欢这种具有枚举性 质的题目,于是把它变成了以下问题:对于任意一个正整数 n≤100000,如何

[HNOI2012]集合选数 --- 状压DP

[HNOI2012]集合选数 题目描述 <集合论与图论>这门课程有一道作业题,要求同学们求出\({1,2,3,4,5}\)的所有满足以 下条件的子集:若 x 在该子集中,则 2x 和 3x 不能在该子集中. 同学们不喜欢这种具有枚举性 质的题目,于是把它变成了以下问题:对于任意一个正整数, 如何求出\({1,2,3...n}\) 的满足上述约束条件的子集的个数(只需输出对 \(10^{9}+1\) 取模的结果),现在这个问题就交给你了. 输入格式: 只有一行,其中有一个正整数 \(n\) 30

bzoj 2734: [HNOI2012]集合选数

Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 779  Solved: 456[Submit][Status][Discuss] Description <集合论与图论>这门课程有一道作业题,要求同学们求出{1, 2, 3, 4, 5}的所有满足以 下条件的子集:若 x 在该子集中,则 2x 和 3x 不能在该子集中.同学们不喜欢这种具有枚举性 质的题目,于是把它变成了以下问题:对于任意一个正整数 n≤100000,如何求出{1, 2,...,

[BZOJ2734][HNOI2012]集合选数

试题描述 <集合论与图论>这门课程有一道作业题,要求同学们求出{1, 2, 3, 4, 5}的所有满足以下条件的子集:若 x 在该子集中,则 2x 和 3x 不能在该子集中.同学们不喜欢这种具有枚举性质的题目,于是把它变成了以下问题:对于任意一个正整数 n≤100000,如何求出{1, 2,..., n} 的满足上述约束条件的子集的个数(只需输出对 1,000,000,001 取模的结果),现在这个问题就交给你了. 输入 只有一行,其中有一个正整数 n,30%的数据满足 n≤20. 输出 仅包

BZOJ_2734_[HNOI2012]集合选数_构造+状压DP

题意:<集合论与图论>这门课程有一道作业题,要求同学们求出{1, 2, 3, 4, 5}的所有满足以 下条件的子集:若 x 在该子集中,则 2x 和 3x 不能在该子集中.同学们不喜欢这种具有枚举性 质的题目,于是把它变成了以下问题:对于任意一个正整数 n≤100000,如何求出{1, 2,..., n} 的满足上述约束条件的子集的个数(只需输出对 1,000,000,001 取模的结果),现在这个问题就 交给你了. 分析: 我们构造出一个矩阵 1 2^0*3^1 2^0*3^2 2^1*3^

[BZOJ2734][HNOI2012] 集合选数(状态压缩+思维)

Description 题目链接 Solution 可以根据条件构造出一个矩阵, 1 3 9 27 81... 2 6 18.... 4 12 36... 这个矩阵满足\(G[i][1]=G[i-1][1]*2(1< i),G[i][j]=G[i][j-1]*3(1\leq i,1<j)\) 也就是要满足不能同时选择矩阵中\((G[i][j],G[i][j+1],G[i+1][j])\) 而且会发现,矩阵可能有多个,应枚举矩阵的\(G[1][1]\)并记录下出现过的数 这样会发现矩阵最大长为1

bzoj2734【HNOI2012】集合选数

2734: [HNOI2012]集合选数 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 831  Solved: 487 [Submit][Status][Discuss] Description <集合论与图论>这门课程有一道作业题,要求同学们求出{1, 2, 3, 4, 5}的所有满足以 下条件的子集:若 x 在该子集中,则 2x 和 3x 不能在该子集中.同学们不喜欢这种具有枚举性 质的题目,于是把它变成了以下问题:对于任意一个正整数

[HNOI2012][BZOJ2734] 集合选数|状态压缩动态规划|思路题

2734: [HNOI2012]集合选数 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 708  Solved: 414[Submit][Status][Discuss] Description <集合论与图论>这门课程有一道作业题,要求同学们求出{1, 2, 3, 4, 5}的所有满足以 下条件的子集:若 x 在该子集中,则 2x 和 3x 不能在该子集中.同学们不喜欢这种具有枚举性 质的题目,于是把它变成了以下问题:对于任意一个正整数 n≤

【BZOJ-2732】集合选数 状压DP (思路题)

2734: [HNOI2012]集合选数 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1070  Solved: 623[Submit][Status][Discuss] Description <集合论与图论>这门课程有一道作业题,要求同学们求出{1, 2, 3, 4, 5}的所有满足以 下条件的子集:若 x 在该子集中,则 2x 和 3x 不能在该子集中.同学们不喜欢这种具有枚举性 质的题目,于是把它变成了以下问题:对于任意一个正整数 n