zoukankan      html  css  js  c++  java
  • [HNOI2012]集合选数(构造,状态压缩,DP)

    神仙题。

    莫名其妙的就试一试把所有数放进一个类似矩阵的东西里面。

    首先把 (1) 放到左上角,然后在每个数的右边放它的 (3) 倍(大于 (n) 就不用放了),下面放它的 (2) 倍(大于 (n) 就不用放了)。

    注意这样子有些数会不在里面。那么从小到大,每次选最小的且没有出现过的数作为一个新的“矩阵”的左上角。容易发现这些“矩阵”互不干扰,对每个矩阵分别求方案数,乘起来就好了。

    对于一个矩阵,发现就是对于一个数,如果它选了,那么它右边和下面的都不能选。

    问题就变成选一些数,互不相邻的方案数。

    由于这个矩阵不会太大(长和宽都是 (log) 级别的),所以直接状压。

    时间复杂度,大力分析一波(我的分析特别松,首先假设所有矩阵都是满的,也就是右下角不会空出一块,然后状压时也不考虑能不能删掉无用状态),会得到一个极其松的上界 (3 imes 10^7)。状压 DP 时剪掉无用状态,就能跑得飞快了。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> PII;
    const int maxn=100010,mod=1000000001;
    #define MP make_pair
    #define PB push_back
    #define lson o<<1,l,mid
    #define rson o<<1|1,mid+1,r
    #define FOR(i,a,b) for(int i=(a);i<=(b);i++)
    #define ROF(i,a,b) for(int i=(a);i>=(b);i--)
    #define MEM(x,v) memset(x,v,sizeof(x))
    inline ll read(){
    	char ch=getchar();ll x=0,f=0;
    	while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar();
    	while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
    	return f?-x:x;
    }
    int n,ans=1,len[18],f[18][2048],ok[2048],ol;
    bool vis[maxn];
    bool check(int x){
    	FOR(i,0,11) if((x>>i)&(x>>(i+1))&1) return false;
    	return true;
    }
    int solve(int x){
    	int y=x,w,s=0;
    	FOR(i,1,n){
    		if(y>n) break;
    		int z=y;
    		FOR(j,1,n){
    			if(z>n) break;
    			len[i]=j;
    			vis[z]=true;
    			z*=3;
    		}
    		w=i;
    		y*=2;
    	}
    	FOR(i,1,ol){
    		if(ok[i]>=(1<<len[1])) break;
    		f[1][i]=1;
    		if(w==1) s=(s+1)%mod;
    	}
    	FOR(i,2,w) FOR(j,1,ol){
    		if(ok[j]>=(1<<len[i])) break;
    		f[i][j]=0;
    		FOR(k,1,ol){
    			if(ok[k]>=(1<<len[i-1])) break;
    			if(!(ok[j]&ok[k])) f[i][j]=(f[i][j]+f[i-1][k])%mod;
    		}
    		if(i==w) s=(s+f[i][j])%mod;
    	}
    	return s;
    }
    int main(){
    	n=read();
    	FOR(i,0,2047) if(check(i)) ok[++ol]=i;
    	FOR(i,1,n) if(!vis[i]) ans=1ll*ans*solve(i)%mod;
    	printf("%d
    ",ans);
    }
    
  • 相关阅读:
    NOIP 2016 提高组 复赛 Day2T1==洛谷2822 组合数问题
    Codevs 1710 == POJ 1190 生日蛋糕 == 洛谷P1731
    [网络流24题] COGS 750 栅格网络流
    [网络流24题] COGS 运输问题1
    狂K 线段树
    Graph coloring技能树
    智能体大赛酱油记
    graph coloring学习记录
    湖北省赛酱油记
    CCCC酱油记
  • 原文地址:https://www.cnblogs.com/1000Suns/p/11372204.html
Copyright © 2011-2022 走看看