zoukankan      html  css  js  c++  java
  • 2734: [HNOI2012]集合选数

    2734: [HNOI2012]集合选数

    链接

    分析:

      转化一下题意。

      1 3 9 27...

      2 6 18 54...

      4 12 36 108...

      8 24 72 216...

      ...

      写成这样的矩阵阵后,那么题意就是不能选相邻的点,求方案数。可以知道行不超过18,列不超过11,然后状压dp即可。

      发现5在这个矩阵中没有出现,于是可以在构造a[1][1]=5的矩阵,利用乘法原理求出相乘。同样地,构成a[1][1]为没有出现的数的矩阵,相乘。

    代码:

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #include<cmath>
    #include<cctype>
    #include<set>
    #include<queue>
    #include<vector>
    #include<map>
    using namespace std;
    typedef long long LL;
    
    inline int read() {
        int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
        for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
    }
    
    const int mod =  1000000001;
    
    int a[20][20], b[20], f[20][2100], n;
    bool vis[100005];
    
    inline void add(int &x,int y) { x += y; if (x >= mod) x -= mod; }
    int Calc(int x) {
        memset(b, 0, sizeof(b));
        a[1][1] = x;
        for (int i = 2; i <= 18; ++i) 
            if ((a[i - 1][1] << 1) <= n) a[i][1] = a[i - 1][1] << 1;
            else a[i][1] = n + 1;    
        for (int i = 1; i <= 18; ++i) 
            for (int j = 2; j <= 11; ++j) 
                if (a[i][j - 1] * 3 <= n) a[i][j] = a[i][j - 1] * 3;
                else a[i][j] = n + 1;
        for (int i = 1; i <= 18; ++i) 
            for (int j = 1; j <= 11; ++j) 
                if (a[i][j] <= n) b[i] += (1 << (j - 1)), vis[a[i][j]] = 1;
        for (int i = 1; i <= 18; ++i) 
            for (int j = 0; j <= b[i]; ++j) f[i][j] = 0;
        f[0][0] = 1;
        for (int i = 0; i < 18; ++i)
            for (int s = 0; s <= b[i]; ++s) 
                if (f[i][s]) 
                    for (int t = 0; t <= b[i + 1]; ++t) 
                        if ((s & t) == 0 && (t & (t >> 1)) == 0) add(f[i + 1][t], f[i][s]);
        return f[18][0];
    }
    
    int main() {
        n = read(); LL ans = 1;
        for (int i = 1; i <= n; ++i) 
            if (!vis[i]) ans = 1ll * ans * Calc(i) % mod; 
        cout << ans;
        return 0;
    }
  • 相关阅读:
    还在写onClickListener()???你OUT拉
    Java 中的reference
    如何将eclipse上的android项目转移到android studio
    List,Set,Map再学习一下
    Java对象实例化的速度的一个试验
    如何自定义ImageView并让其渐变出现(李刚老师)
    android studio 中git插件的使用 github项目的配置及操作
    eGit插件
    原来Linux才是深入学习3D的好去处【原创】
    用FileMapping跨进程共享数据
  • 原文地址:https://www.cnblogs.com/mjtcn/p/10467205.html
Copyright © 2011-2022 走看看