zoukankan      html  css  js  c++  java
  • HDU 6984

    题面传送门

    傻逼卡常屑题/bs/bs,大概现场过得人比较少的原因就是它比较卡常罢(Fog

    首先对于这样的题我们很难直接维护,不过注意到这个 (n=300) 给得很灵性,(k) 比较小和 (k) 比较大时各有自己的优势。因此考虑进行数据分治,也就是我们设一个阈值 (B),那么对于 (kle B) 的情况是相对来说比较容易的,就设一个 (dp_{i,S}) 表示考虑到第 (i) 个位置,过去 (k) 个位置选择/不选择的状态为 (S) 的美丽程度之和,转移就枚举下一个位置选/不选即可实现 (mathcal O(1)) 转移,时间复杂度 (n2^B)

    对于 (k>B) 的情况,我们考虑将序列想象成一个 (lceildfrac{n}{k} ceil)(k) 列的矩阵,第 (i) 行包含了 ([(i-1)k+1,ik]) 位置上的值(如果超过了 (n) 就在后面补 (0)),那么本题的限制等价于不能同时选择矩阵中相邻的元素,并且对于所有 (1le i<lceildfrac{n}{k} ceil),第 (i) 行最后一个元素和第 (i+1) 行第一个元素不能同时被选择,那么如果说之前 (kle B) 的情况是按行状压,那么 (k>B) 的情况也就自然可以想到按列状压了,不过由于本题对于第一列与最后一列还有额外的限制,因此考虑首先枚举第一列选择/不选择的状态,然后记 (dp_{i,S}) 表示考虑到第 (i) 列,第 (i) 列选择/不选择的状态为 (S) 的所有方案的美丽程度之和,转移就枚举下一列的状态即可,时间复杂度 (mathcal O(n8^{n/B}))

    考虑优化,首先如果直接按照上面的做法做那直接 T 飞——不论你 (B) 取啥值。不过注意到对于这一类状压 (dp),合法的状态数通常是比较少的,如果你手比较勤快打个表也能发现 ([0,2^k-1]) 中不存在二进制下不存在两个相邻的 (1) 的数恰有 (Fib_{k+2}) 个,因此可以直接一遍将符合条件的数筛出来,那么复杂度就降到了 (nFib_{B+2})(n·Fib_{n/B+2}^3),不过还是过不去。注意到对于 (k) 比较小的暴力已经没啥优化的空间了,因此考虑优化 (k) 比较大的暴力,首先我们枚举下一列的状态时候答案的贡献可以预处理出来,这样 (n·Fib_{n/B+2}^3) 就降到了 (k·Fib_{n/B+2}^3),其次对于两个合法状态 (j,k),满足 (j&k=0)((j,k)) 数量是小于 (Fib_{n/B+2}^2) 的,大约是 (Fib_{n/B+2}^2) 的一半,因此考虑将这个东西进一步预处理出来,这样常数就可以小一半。

    实测 (B=25) 时复杂度最优,(kle 25) 部分复杂度大约是 (300·3 imes 10^5=9 imes 10^7)(k>25) 部分复杂度大概是 (377·26·47321=4 imes 10^8),不过对于 (n=300,k=25)(n=300,k=26),我的程序似乎都只跑了 1.5s?话说回来由于这题出题人没有把数据卡满,因此这样的复杂度可以通过此题。否则肯定直接 T 飞。

    所以说,下次看到 (200,300) 这样的数据范围,不要再拘泥地想什么 (n^3,n^2log n) 了,有时候数据分治/根号分治+状压 (dp) 也可以出到类似的数据范围。

    最后我稍微说一句,赛场上我使用的 vector 预处理合法的状态然后直接 T 飞,(n=300,k=25) 的数据跑了 4s,事实上直接每组数据都 (2^k) 跑一遍也行。

    所以以后别用 vector 了(光速逃

    完整代码:(为什么这次要放完整代码呢?因为可以康到三个火车头粘在一起占据程序大部分空间的壮丽景象)

    #pragma GCC optimize(2)
    #pragma GCC optimize(3)
    #pragma GCC target("avx")
    #pragma GCC optimize("Ofast")
    #pragma GCC optimize("inline")
    #pragma GCC optimize("-fgcse")
    #pragma GCC optimize("-fgcse-lm")
    #pragma GCC optimize("-fipa-sra")
    #pragma GCC optimize("-ftree-pre")
    #pragma GCC optimize("-ftree-vrp")
    #pragma GCC optimize("-fpeephole2")
    #pragma GCC optimize("-ffast-math")
    #pragma GCC optimize("-fsched-spec")
    #pragma GCC optimize("unroll-loops")
    #pragma GCC optimize("-falign-jumps")
    #pragma GCC optimize("-falign-loops")
    #pragma GCC optimize("-falign-labels")
    #pragma GCC optimize("-fdevirtualize")
    #pragma GCC optimize("-fcaller-saves")
    #pragma GCC optimize("-fcrossjumping")
    #pragma GCC optimize("-fthread-jumps")
    #pragma GCC optimize("-funroll-loops")
    #pragma GCC optimize("-fwhole-program")
    #pragma GCC optimize("-freorder-blocks")
    #pragma GCC optimize("-fschedule-insns")
    #pragma GCC optimize("inline-functions")
    #pragma GCC optimize("-ftree-tail-merge")
    #pragma GCC optimize("-fschedule-insns2")
    #pragma GCC optimize("-fstrict-aliasing")
    #pragma GCC optimize("-fstrict-overflow")
    #pragma GCC optimize("-falign-functions")
    #pragma GCC optimize("-fcse-skip-blocks")
    #pragma GCC optimize("-fcse-follow-jumps")
    #pragma GCC optimize("-fsched-interblock")
    #pragma GCC optimize("-fpartial-inlining")
    #pragma GCC optimize("no-stack-protector")
    #pragma GCC optimize("-freorder-functions")
    #pragma GCC optimize("-findirect-inlining")
    #pragma GCC optimize("-frerun-cse-after-loop")
    #pragma GCC optimize("inline-small-functions")
    #pragma GCC optimize("-finline-small-functions")
    #pragma GCC optimize("-ftree-switch-conversion")
    #pragma GCC optimize("-foptimize-sibling-calls")
    #pragma GCC optimize("-fexpensive-optimizations")
    #pragma GCC optimize("-funsafe-loop-optimizations")
    #pragma GCC optimize("-fdelete-null-pointer-checks")
    #pragma GCC optimize(2)
    #pragma GCC optimize(3)
    #pragma GCC target("avx")
    #pragma GCC optimize("Ofast")
    #pragma GCC optimize("inline")
    #pragma GCC optimize("-fgcse")
    #pragma GCC optimize("-fgcse-lm")
    #pragma GCC optimize("-fipa-sra")
    #pragma GCC optimize("-ftree-pre")
    #pragma GCC optimize("-ftree-vrp")
    #pragma GCC optimize("-fpeephole2")
    #pragma GCC optimize("-ffast-math")
    #pragma GCC optimize("-fsched-spec")
    #pragma GCC optimize("unroll-loops")
    #pragma GCC optimize("-falign-jumps")
    #pragma GCC optimize("-falign-loops")
    #pragma GCC optimize("-falign-labels")
    #pragma GCC optimize("-fdevirtualize")
    #pragma GCC optimize("-fcaller-saves")
    #pragma GCC optimize("-fcrossjumping")
    #pragma GCC optimize("-fthread-jumps")
    #pragma GCC optimize("-funroll-loops")
    #pragma GCC optimize("-fwhole-program")
    #pragma GCC optimize("-freorder-blocks")
    #pragma GCC optimize("-fschedule-insns")
    #pragma GCC optimize("inline-functions")
    #pragma GCC optimize("-ftree-tail-merge")
    #pragma GCC optimize("-fschedule-insns2")
    #pragma GCC optimize("-fstrict-aliasing")
    #pragma GCC optimize("-fstrict-overflow")
    #pragma GCC optimize("-falign-functions")
    #pragma GCC optimize("-fcse-skip-blocks")
    #pragma GCC optimize("-fcse-follow-jumps")
    #pragma GCC optimize("-fsched-interblock")
    #pragma GCC optimize("-fpartial-inlining")
    #pragma GCC optimize("no-stack-protector")
    #pragma GCC optimize("-freorder-functions")
    #pragma GCC optimize("-findirect-inlining")
    #pragma GCC optimize("-frerun-cse-after-loop")
    #pragma GCC optimize("inline-small-functions")
    #pragma GCC optimize("-finline-small-functions")
    #pragma GCC optimize("-ftree-switch-conversion")
    #pragma GCC optimize("-foptimize-sibling-calls")
    #pragma GCC optimize("-fexpensive-optimizations")
    #pragma GCC optimize("-funsafe-loop-optimizations")
    #pragma GCC optimize("-fdelete-null-pointer-checks")
    #pragma GCC optimize(2)
    #pragma GCC optimize(3)
    #pragma GCC target("avx")
    #pragma GCC optimize("Ofast")
    #pragma GCC optimize("inline")
    #pragma GCC optimize("-fgcse")
    #pragma GCC optimize("-fgcse-lm")
    #pragma GCC optimize("-fipa-sra")
    #pragma GCC optimize("-ftree-pre")
    #pragma GCC optimize("-ftree-vrp")
    #pragma GCC optimize("-fpeephole2")
    #pragma GCC optimize("-ffast-math")
    #pragma GCC optimize("-fsched-spec")
    #pragma GCC optimize("unroll-loops")
    #pragma GCC optimize("-falign-jumps")
    #pragma GCC optimize("-falign-loops")
    #pragma GCC optimize("-falign-labels")
    #pragma GCC optimize("-fdevirtualize")
    #pragma GCC optimize("-fcaller-saves")
    #pragma GCC optimize("-fcrossjumping")
    #pragma GCC optimize("-fthread-jumps")
    #pragma GCC optimize("-funroll-loops")
    #pragma GCC optimize("-fwhole-program")
    #pragma GCC optimize("-freorder-blocks")
    #pragma GCC optimize("-fschedule-insns")
    #pragma GCC optimize("inline-functions")
    #pragma GCC optimize("-ftree-tail-merge")
    #pragma GCC optimize("-fschedule-insns2")
    #pragma GCC optimize("-fstrict-aliasing")
    #pragma GCC optimize("-fstrict-overflow")
    #pragma GCC optimize("-falign-functions")
    #pragma GCC optimize("-fcse-skip-blocks")
    #pragma GCC optimize("-fcse-follow-jumps")
    #pragma GCC optimize("-fsched-interblock")
    #pragma GCC optimize("-fpartial-inlining")
    #pragma GCC optimize("no-stack-protector")
    #pragma GCC optimize("-freorder-functions")
    #pragma GCC optimize("-findirect-inlining")
    #pragma GCC optimize("-frerun-cse-after-loop")
    #pragma GCC optimize("inline-small-functions")
    #pragma GCC optimize("-finline-small-functions")
    #pragma GCC optimize("-ftree-switch-conversion")
    #pragma GCC optimize("-foptimize-sibling-calls")
    #pragma GCC optimize("-fexpensive-optimizations")
    #pragma GCC optimize("-funsafe-loop-optimizations")
    #pragma GCC optimize("-fdelete-null-pointer-checks")
    #pragma comment(linker,"/stack:200000000")
    #pragma GCC optimize("Ofast,no-stack-protector")
    #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
    #include <bits/stdc++.h>
    using namespace std;
    #define fi first
    #define se second
    #define fill0(a) memset(a,0,sizeof(a))
    #define fill1(a) memset(a,-1,sizeof(a))
    #define fillbig(a) memset(a,63,sizeof(a))
    #define pb push_back
    #define ppb pop_back
    #define mp make_pair
    #define y1 y1111111
    #define eprintf(...) fprintf(stderr,__VA_ARGS__)
    template<typename T1,typename T2> void chkmin(T1 &x,T2 y){if(x>y) x=y;}
    template<typename T1,typename T2> void chkmax(T1 &x,T2 y){if(x<y) x=y;}
    typedef pair<int,int> pii;
    typedef long long ll;
    typedef unsigned int u32;
    typedef unsigned long long u64;
    namespace fastio{
    	#define FILE_SIZE 1<<23
    	char rbuf[FILE_SIZE],*p1=rbuf,*p2=rbuf,wbuf[FILE_SIZE],*p3=wbuf;
    	inline char getc(){return p1==p2&&(p2=(p1=rbuf)+fread(rbuf,1,FILE_SIZE,stdin),p1==p2)?-1:*p1++;}
    	inline void putc(char x){(*p3++=x);}
    	template<typename T> void read(T &x){
    		x=0;char c=getchar();T neg=0;
    		while(!isdigit(c)) neg|=!(c^'-'),c=getchar();
    		while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar();
    		if(neg) x=(~x)+1;
    	}
    	template<typename T> void recursive_print(T x){return (!x)?void():(recursive_print(x/10),putc(x%10^48),void());}
    	template<typename T> void print(T x){(!x)&&(putc('0'),0);(x<0)&&(putc('-'),x=~x+1);recursive_print(x);}
    	template<typename T> void print(T x,char c){(!x)&&(putc('0'),0);(x<0)&&(putc('-'),x=~x+1);recursive_print(x);putc(c);}
    	void print_final(){fwrite(wbuf,1,p3-wbuf,stdout);}
    }
    const int MAXN=300;
    const int MOD=1e9+7;
    int n,k,w[MAXN+5];
    namespace sub1{
    	const int MAX=3e5;
    	int st[MAX+5],rid[(1<<25)+5],lim=0;
    	int dp[2][MAX+5];
    	void solve(){
    		lim=0;
    		for(int i=0;i<(1<<k);i++) (!(i&(i<<1)))?(st[++lim]=i,rid[i]=lim):rid[i]=0;
    		for(int j=1;j<=lim;j++) dp[0][j]=dp[1][j]=0;
    		dp[0][rid[0]]=1;int pre=0,nxt=1;
    		for(int i=1;i<=n;i++){
    			for(int j=1;j<=lim;j++) dp[nxt][j]=0;
    			for(int j=1;j<=lim;j++) if(dp[pre][j]){
    				int s=st[j],t=(s<<1)&((1<<k)-1);(dp[nxt][rid[t]]+=dp[pre][j])%=MOD;
    				if((~s&1)&&(~s>>(k-1)&1)) (dp[nxt][rid[t|1]]+=1ll*dp[pre][j]*w[i]%MOD)%=MOD;
    			} swap(pre,nxt);
    		} int ans=0;for(int i=1;i<=lim;i++) (ans+=dp[pre][i])%=MOD;
    		printf("%d
    ",(ans-1+MOD)%MOD);
    	}
    }
    namespace sub2{
    	const int MAX=1e3;
    	int st[MAX+5],rid[(1<<12)+5];
    	int dp[MAXN+5][MAX+5],mul[MAXN+5][MAX+5],lim=0;
    	int can[MAX+5][MAX+5];
    	void solve(){
    		int bt=n/k+1,ans=0;lim=0;
    		for(int i=0;i<(1<<bt);i++) (!(i&(i<<1)))?(st[++lim]=i,rid[i]=lim):rid[i]=0;
    		for(int i=1;i<=k;i++) for(int j=1;j<=lim;j++) mul[i][j]=0;
    		for(int i=1;i<=k;i++) for(int j=1;j<=lim;j++){
    			int s=st[j];
    			if(n/k*k+i>n&&(s>>(bt-1)&1)) continue;
    			mul[i][j]=1;
    			for(int l=0;l<bt;l++) if(s>>l&1)
    				mul[i][j]=1ll*mul[i][j]*w[l*k+i]%MOD;
    		}
    		for(int i=1;i<=lim;i++) can[i][0]=0;
    		for(int i=1;i<=lim;i++) for(int j=1;j<=lim;j++)
    			if(!(st[i]&st[j])) can[i][++can[i][0]]=j;
    		for(int i=1;i<=lim;i++){
    //			printf("%d
    ",i);
    			int s=st[i];
    			if(n/k*k+k>n&&(s>>(bt-1)&1)) continue;
    			for(int j=1;j<=k;j++) for(int l=1;l<=lim;l++) dp[j][l]=0;
    			dp[k][i]=mul[k][i];
    			for(int j=k;j>=2;j--) for(int l=1;l<=lim;l++) if(dp[j][l]){
    				for(int o=1;o<=can[l][0];o++)
    					(dp[j-1][can[l][o]]+=1ll*mul[j-1][can[l][o]]*dp[j][l]%MOD)%=MOD;
    			} for(int l=1;l<=lim;l++) if(!(st[l]&(s<<1))) (ans+=dp[1][l])%=MOD;
    		} printf("%d
    ",(ans-1+MOD)%MOD);
    	}
    }
    void solve(){
    	scanf("%d%d",&n,&k);
    	for(int i=1;i<=n;i++) scanf("%d",&w[i]);
    	if(n<=100) (k<=15)?sub1::solve():sub2::solve();
    	else (k<=25)?sub1::solve():sub2::solve();
    }
    int main(){
    	int qu;scanf("%d",&qu);
    	while(qu--) solve();
    	return 0;
    }
    
  • 相关阅读:
    PullToRefresh原理解析,pulltorefresh解析
    instanceof和isInstance(Object obj) 和isAssignableFrom(Class cls)的区别和联系
    instanceof和isInstance(Object obj) 和isAssignableFrom(Class cls)的区别和联系
    ListView / GirdView Adpater的getView方法,首项多次调用
    ListView / GirdView Adpater的getView方法,首项多次调用
    Android中View大小的确定过程
    StrictMode 详解
    StrictMode 详解
    ListView中的Item不能点击的解决方法
    ListView中的Item不能点击的解决方法
  • 原文地址:https://www.cnblogs.com/ET2006/p/hdu-6984.html
Copyright © 2011-2022 走看看