博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[HNOI2012]集合选数
阅读量:6698 次
发布时间:2019-06-25

本文共 2080 字,大约阅读时间需要 6 分钟。

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
3 #include
4 #include
5 #include
6 #include
7 #include
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

你可能感兴趣的文章
栈溢出笔记1.3 准备Shellcode
查看>>
Oracle 存储过程错误之PLS-00201: 必须声明标识符
查看>>
Android开发中无处不在的设计模式——动态代理模式
查看>>
You have new mail in /var/spool/mail/root消除提示的方法
查看>>
mysql存储引擎的一点学习心得总结
查看>>
jsp 中包含 一个路径为变量的文件
查看>>
[js高手之路] 跟GhostWu一起封装一个字符串工具库-扩展字符串位置方法(4)
查看>>
正则正整数含0
查看>>
关键字: on
查看>>
Ubuntu & GitLab CI & Docker & ASP.NET Core 2.0 自动化发布和部署(1)
查看>>
Introduction to the Optimizer --cbo
查看>>
Spring4.0之四:Meta Annotation(元注解)
查看>>
《jQuery基础》总结
查看>>
[hadoop] kettle spoon 基础使用 (txt 内容抽取到excel中)
查看>>
Linux kernel的中断子系统之(二):IRQ Domain介绍
查看>>
[Oracle]快速构造大量数据的方法
查看>>
you have mixed tabs and spaces fix this
查看>>
30天自制操作系统(二)汇编语言学习与Makefile入门
查看>>
CentOS7设置自定义开机启动,添加自定义系统服务
查看>>
Angular4学习笔记(六)- Input和Output
查看>>