• [HNOI2012]集合选数(状压DP+构造)


    题目要求若出现x,则不能出现2x,3x

    所以我们考虑构造一个矩阵

    (1 2 4 8……)

    (3 6 12 24……)

    (9 18 36……)

    (……)

    不难发现,对于一个矩阵,若我选择了一个数x,则在矩阵内该数的相邻格子都不能选,题目就被转化成了玉米田了,可以用状压DP解决

    但是直接做是不对的,比如5就没有出现在这个序列中

    所以我们可以构造多个矩阵,用乘法原理统计答案即可

    #include<bits/stdc++.h>
    using namespace std;
    #define il inline
    #define re register
    #define debug printf("Now is Line : %d
    ",__LINE__)
    #define file(a) freopen(#a".in","r",stdin);//freopen(#a".out","w",stdout)
    #define int long long
    #define inf 123456789
    #define mod 1000000001
    il int read() {
        re int x = 0, f = 1; re char c = getchar();
        while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar();}
        while(c >= '0' && c <= '9') x = x * 10 + c - 48, c = getchar();
        return x * f;
    }
    #define rep(i, s, t) for(re int i = s; i <= t; ++ i)
    #define drep(i, s, t) for(re int i = t; i >= s; -- i)
    #define mem(k, p) memset(k, p, sizeof(k))
    #define maxn 100005
    int n, m, a[20][20], g[1 << 15], vis[maxn], H, L[20], dp[20][1 << 15], ans = 1;
    il void martix(int x) {
        H = 0;
        rep(i, 1, 18) {
            a[i][1] = (i == 1) ? x : a[i - 1][1] * 2;
            if(a[i][1] > n) break;
            ++ H, L[i] = vis[a[i][1]] = 1;
            rep(j, 2, 11) {
                a[i][j] = a[i][j - 1] * 3;
                if(a[i][j] > n) break;
                L[i] = j, vis[a[i][j]] = 1;
            }
        }
    }
    il int solve() {
        rep(i, 0, (1 << L[1]) - 1) dp[1][i] = g[i];
        rep(i, 2, H) {
            rep(j, 0, (1 << L[i]) - 1) {
                if(!g[j]) continue;
                dp[i][j] = 0;
                rep(k, 0, (1 << L[i - 1]) - 1) {
                    if(g[k] && (k & j) == 0) dp[i][j] += dp[i - 1][k];
                }
            }
        }
        int t = 0;
        rep(i, 0, (1 << L[H]) - 1) t = (t + dp[H][i]) % mod;
        return t;
    }
    signed main() {
        n = read();
        rep(i, 0, (1 << 11) - 1) g[i] = !(i & (i << 1));
        rep(i, 1, n) if(!vis[i]) martix(i), ans = ans * solve() % mod;
        printf("%lld", ans);
        return 0;
    }
    
  • 相关阅读:
    李白—烂尾楼题记
    [原创]网络图片延迟加载实现,超越jquery2010年3月26日
    利用反射,泛型,扩展方法快速获取表单值到实体类
    断点续传 到底是很么
    认识LINQ
    Gridview控件用法大总结
    网站性能优化总结。
    JQ小技巧
    自己写的jq_3个小插件
    MOSS中SPuser类的使用
  • 原文地址:https://www.cnblogs.com/bcoier/p/10788835.html
Copyright © 2020-2023  润新知