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);
    }
    
  • 相关阅读:
    学习bootsect.s中经常会问到的问题
    c++资源之不完全导引(全文) (转载)
    bootsect.S (读核笔记系列)
    WAP开发FAQ
    学习使用groovy(翻译稿之第一章)
    "革命尚未成功,同志仍需努力!"
    JAVA中this用法小结(转)
    Android <Button>样式的设置方法
    最新SDK android开发环境搭建
    Android中的数据存取(一)Preference
  • 原文地址:https://www.cnblogs.com/1000Suns/p/11372204.html
Copyright © 2011-2022 走看看