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

    我们构造一个矩阵,左上角为1,右边的数为左边的数*3,下边的数为上边的数*2,那么这个矩阵的列数不会超过11,行数不会超过17

    对于矩阵中的数,只要选出的两个数的位置不是四联通,就是合法的

    状压一行,转移

    可能有多个矩阵,即左上角不一定是1

    枚举左上角,且保证这个数不被包含在其他矩阵中,那么矩阵之间就没有相同的数,互不影响,乘法原理即可

    #include<cstdio>
    using namespace std;
    const int mod=1e9+1;
    int n,A[18][18],F[18][10005],line[18],vis[100005];
    int solve(int ST){
    	int M;
    	A[0][0]=ST;
    	for (M=0; A[M][0]<=n; M++) A[M+1][0]=A[M][0]*2;
    	for (int i=0; i<M; i++)
    		for (line[i]=0; A[i][line[i]]<=n; line[i]++) {
    			vis[A[i][line[i]]]=1;
    			A[i][line[i]+1]=A[i][line[i]]*3;
    		}
    	for (int i=0; i<M; i++)
    		for (int j=0; j<(1<<line[i]); j++)
    			F[i][j]=0;
    	for (int i=0; i<(1<<line[0]); i++) 
    		if (!(i&(i>>1))) F[0][i]=1;
    	for (int i=0; i<M-1; i++)
    		for (int pre=0; pre<(1<<line[i]); pre++)
    			if (F[i][pre])
    				for (int now=0; now<(1<<line[i+1]); now++)
    					if (!(now&(now>>1)) && !(pre&now)) (F[i+1][now]+=F[i][pre])%=mod;
    	int ans=0;
    	for (int i=0; i<(1<<line[M-1]); i++) (ans+=F[M-1][i])%=mod;
    	return ans;
    }
    int main(){
    	scanf("%d",&n);
    	int ans=1;
    	for (int i=1; i<=n; i++)
    		if (!vis[i]) ans=1ll*ans*solve(i)%mod;
    	printf("%d
    ",ans);
    	return 0;
    }
    

      

  • 相关阅读:
    工作流调度器Azkaban的安装配置
    MySQL初学入门基础知识-sql语句
    spark大数据生态架构
    快速排序算法——分析及总结 (非常好)
    经典的大数据面试题总结
    flume采集数据报错问题解决
    haproxy官方文档
    问题
    2016/6/7学习记录
    2016
  • 原文地址:https://www.cnblogs.com/silenty/p/9867114.html
Copyright © 2011-2022 走看看