zoukankan      html  css  js  c++  java
  • 【BZOJ2734】【HNOI2012】集合选数(状态压缩,动态规划)

    【BZOJ2734】【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

    Hint

    【样例解释】

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

    题解

    这题太好了,
    这题真的是好题
    好神奇的做法

    找个矩形出来

    1   2   4   8   16  .....
    3   6   12  24  48  .....
    9   18  36  72  144 .....
    .   .   .   .   .   .   .
    .   .   .   .   .   .   .
    

    然后,就变成了,有若干个这样的矩阵
    求出选不相邻的数的选法数
    So Easy呀。。。
    但是真心想不到

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<vector>
    using namespace std;
    #define MOD 1000000001
    inline int read()
    {
    	int x=0,t=1;char ch=getchar();
    	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    	if(ch=='-')t=-1,ch=getchar();
    	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    	return x*t;
    }
    /*
    这题真的好神奇...
    构造一个矩形出来看看
    1   2   4   8   16  .....
    3   6   12  24  48  .....
    9   18  36  72  144 .....
    .   .   .   .   .   .   .
    .   .   .   .   .   .   .
    很神奇呀
    题目就变成了,有若干个这样的矩形,
    每次可以从矩形中选择不相邻的数,问有多少选法
    然后状压DP就可以了
    */
    int f[20][1<<12],N;
    int ss[20];
    bool p[1<<12];
    bool check(int x)
    {
    	return p[x];
    }
    int solve(int x)
    {
    	memset(f,0,sizeof(f));
    	memset(ss,0,sizeof(ss));
    	f[0][0]=1;
    	int n=0,s;
    	for(n=1,s=x;s<=N;++n,s*=2)
    		for(int k=s;k<=N;k*=3)ss[n]++;n--;
    	for(int i=1;i<=n;++i)
    	{
    		for(int j=0;j<(1<<ss[i-1]);++j)
    		{
    			if(!check(j))continue;
    			for(int k=0;k<(1<<ss[i]);++k)
    			{
    				if(!check(k))continue;
    				if(j&k)continue;
    				f[i][k]=(f[i][k]+f[i-1][j])%MOD;
    			}
    		}
    	}
    	int re=0;
    	for(int i=0;i<(1<<ss[n]);++i)re=(re+f[n][i])%MOD;
    	return re;
    }
    int main()
    {
    	N=read();
    	for(int i=0;i<(1<<12);++i)
    		if(!(i&(i<<1))&&!(i&(i>>1)))p[i]=true;
    	int ans=1;
    	for(int i=1;i<=N;++i)
    		if((i%2)&&(i%3))ans=(1LL*ans*solve(i))%MOD;
    	printf("%d
    ",ans);
    	return 0;
    }
    
    
  • 相关阅读:
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    Oracle数据库基础
    软件项目开发模式——三层模式
    JavaWeb——Ajax与MVC学习总结
    JavaWeb——EL及JSTL学习总结
    JavaWeb——过滤器及监听器
    JavaWeb——Servlet开发
  • 原文地址:https://www.cnblogs.com/cjyyb/p/7708634.html
Copyright © 2011-2022 走看看