码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ2734: [HNOI2012]集合选数

时间:2018-03-17 17:52:01      阅读:158      评论:0      收藏:0      [点我收藏+]

标签:define   ++   algo   body   str   span   efi   post   using   

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}。
 
 
这道题很有意思,一开始也往dp那方面想了
但是这道题太妙了,又刷新了我的三观
这道题的关键在于,你把两个限制条件转化成矩阵:

1 3  9  27…

2 6 18 54…

4 12 36 108…

然后跑状压dp即可

 

代码如下:

#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#define Mod 1000000001
using namespace std;
typedef long long ll;
bool v[210000];
int a[21][21];
ll f[21][210000];
int bin[21];
int n;
ll solve(int x)
{
    a[1][1]=x;
    int top;
    for(int i=1;i;i++)
    {
        if(i!=1)
        {
            a[i][1]=a[i-1][1]*2;
            if(a[i][1]>n){top=i-1;break;}
        }
        v[a[i][1]]=false;
        for(int j=2;j;j++)
        {
            a[i][j]=a[i][j-1]*3;
            if(a[i][j]>n){bin[i]=j-1;break;}
            v[a[i][j]]=0;
        }
    }
    bin[0]=1;
    for(int i=0;i<=top;i++)
        for(int j=0;j<(1<<bin[i]);j++)
            f[i][j]=0;
    bin[top+1]=0,f[top+1][0]=0;
    f[0][0]=1;
    for(int i=0;i<=top;i++)
        for(int j=0;j<(1<<bin[i]);j++)
            if(f[i][j])
            {
                if(j&(j>>1))continue;
                for(int k=0;k<(1<<bin[i+1]);k++)
                {
                    if(j&k)continue;
                    f[i+1][k]=(f[i+1][k]+f[i][j])%Mod;
                }
            }
    return f[top+1][0];
}
int main()
{
    scanf("%d",&n);
    ll ans=1;
    memset(v,true,sizeof(v));
    for(int i=1;i<=n;i++)
        if(v[i]==true)
            ans=(ans*(solve(i)%Mod))%Mod;
    printf("%d\n",ans);
    return 0;
}

by_lmy

BZOJ2734: [HNOI2012]集合选数

标签:define   ++   algo   body   str   span   efi   post   using   

原文地址:https://www.cnblogs.com/MT-LI/p/8590924.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!