zoukankan      html  css  js  c++  java
  • Luogu P3226 [HNOI2012]集合选数

    题目
    这题的构造还是挺妙的。
    我们构造一个数表,左上角为(1),每个元素是上面那个元素的(2)倍,左边那个元素的(3)倍。
    那么题目的要求就转化成了在数表中选一堆元素,保证没有元素相互之间是四相邻(上下左右)的。因为一个数表最多是(11*17)的,所以我们可以状压dp。
    显然一个数表无法包含(1sim n)的所有元素,我们把最小的未被包含的拿出来再建一个数表,直到没有未被包含的元素为止。
    由乘法原理可知,总的答案等于每个数表的答案的乘积。

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int P=1000000001;
    int inc(int a,int b){a+=b;return a>=P? a-P:a;}
    int mul(int a,int b){return 1ll*a*b%P;}
    int n,vis[100001],flg[2049],num[19],f[19][2049],ans=1;
    void work(int x)
    {
        int i,j,k,m=1,sum=0;memset(f,0,sizeof f),memset(num,0,sizeof num);
        for(i=x;i<=n;i<<=1,++m) for(j=i;j<=n;j*=3) ++num[m],vis[j]=1;
        for(i=0;i<1<<num[1];++i) f[1][i]=flg[i];
        for(i=2;i<m;++i) for(j=0;j<1<<num[i-1];++j) for(k=0;k<1<<num[i];++k) if(flg[j]&&flg[k]&&!(j&k)) f[i][k]=inc(f[i][k],f[i-1][j]);
        for(i=0;i<1<<num[m-1];++i) sum=inc(sum,f[m-1][i]);
        ans=mul(ans,sum);
    }
    int main()
    {
        int i;cin>>n;
        for(i=0;i<=2048;++i) flg[i]=i<<1&i? 0:1;
        for(i=1;i<=n;++i) if(!vis[i]) work(i);
        cout<<ans;
    }
    
  • 相关阅读:
    js中的投掷筛子的小游戏
    js俩习题
    python中socket理论
    python实现计时器(装饰器)
    python之正则表达式(re模块)用法总结
    python练习题之随机生成验证码
    python中模块介绍
    python中的装饰器基本理论
    python类与对象练习题扑克牌
    Java抓取网页数据
  • 原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/11735195.html
Copyright © 2011-2022 走看看