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

    [BZOJ2734] [HNOI2012]集合选数

    蒻得不行的我觉得这是一道比较难的题,以至于我卡了很久

    可以看出,所有会互相直接造成影响的数之间构成一张\(DAG\),边就是\(i->i*2,i->i*3\)

    取出每一个连通块之后,连了边的点不能同时选,就是一个独立集个数的问题

    \(DAG\)还可以求独立集?

    我们其实可以惊人得发现,这张\(DAG\)过于整齐,每个点都是至多两条出边,就是一个网格图,转化成一张网格图上相邻的点不能取的问题

    这个,状压矩阵即可\(dp[i][S]\)

    
    const int N=1e5+10,P=1e9+1;
     
     
     
    int n;
    ll dp[20][1<<11];
    int A[20];
     
    ll Solve(int i){ 
        int t=0;
        A[0]=0;
        dp[0][0]=1;
        for(;i<=n;i*=2) {//网格图的列数
            t++;
            A[t]=0;
            int c=0;
            for(int j=i;j<=n;j*=3) A[t]|=1<<(c++); //取出网格图这一行的大小
            rep(j,0,A[t]) dp[t][j]=0;
            rep(S1,0,A[t-1]) {
                int fl=1;
                rep(j,0,c+1) if((S1&(1<<j)) && (S1&(1<<(j+1)))) fl=0;
                if(!fl) continue;
                int R=A[t]^(S1&A[t]);
                for(reg int S2=R;;S2=(S2-1)&R) {
                    int fl=1;
                    rep(j,0,c-1) if((S2&(1<<j)) && (S2&(1<<(j+1)))) fl=0;
                    if(!fl) {
                        if(!S2) break;
                        continue;
                    }
                    (dp[t][S2]+=dp[t-1][S1])%=P;
                    if(!S2) break;
                }
            }
        }
        ll res=0;
        rep(i,0,A[t]) res+=dp[t][i];
        res%=P;
        return res;
    }
     
     
     
    int main(){
        n=rd();
        ll ans=1;
        rep(i,1,n) {
            if(i%2==0||i%3==0) continue;
            //这是一个联通块中最左上角的点
            ans=ans*Solve(i)%P;
        }
        printf("%lld\n",ans);
    }
     
    
  • 相关阅读:
    BZOJ 3631 链剖+差分
    BZOJ 1103 DFS序+线段树
    BZOJ 3629 约数和定理+搜索
    198. House Robber
    152. Maximum Product Subarray
    139. Word Break
    132. Palindrome Partitioning II
    120. Triangle
    115. Distinct Subsequences
    97. Interleaving String
  • 原文地址:https://www.cnblogs.com/chasedeath/p/11665106.html
Copyright © 2011-2022 走看看