zoukankan      html  css  js  c++  java
  • agc035_e Develop

    agc035_e Develop

    https://atcoder.jp/contests/agc035/tasks/agc035_e

    UmWrZV.png

    Tutorial

    https://blog.csdn.net/qq_38609262/article/details/103058291

    考虑被删除的数的集合(S)应该满足什么条件.

    首先,显然只有([1,N])的数才可以被删除,然后应该存在某种(S)中元素顺序使得按这个顺序删除时不会写上任何数字.

    考虑对于(x),向(x-2,x+K)连边,那么上面的条件相当于顶点集合(S)的诱导子图不存在环.此时拓扑序就是这个顺序.

    注意向后的只有(x-2),所以考虑将([1,N])按奇偶分为两条链.

    (K)为偶数时,环只会出现在一条链上,相当于一条链上不能出现连续(dfrac K2)个被选的数.设(dp(i,j))表示现在在第(i)个点,接下来会有(j)个连续的点被选择.(O(n^2))即可.

    (K)为奇数时,环的形状如下

    Um4nGF.jpg

    (dp(i,j,k))表示现在已经考虑了奇链上前(i)个点和偶链上前(i+lfloor dfrac K2 floor)个点,奇链第(i)个点后会有连续(j)个点,偶链第(i+lfloor dfrac K2 floor)个点前有连续(k)个连续的点,转移时考虑两条链上接下来的点的状态,两个点可以同时加入(S)集合当且仅当不会出现上面那样的环.具体判断可参考代码,复杂度(O(n^3))

    Code

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #define debug(...) fprintf(stderr,__VA_ARGS__)
    using namespace std;
    inline char gc() {
    	return getchar();
    	static char buf[100000],*l=buf,*r=buf;
    	return l==r&&(r=(l=buf)+fread(buf,1,100000,stdin),l==r)?EOF:*l++;
    }
    template<class T> void rd(T &x) {
    	x=0; int f=1,ch=gc();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
    	while(ch>='0'&&ch<='9'){x=x*10-'0'+ch;ch=gc();}
    	x*=f;
    }
    typedef long long ll;
    const int MAXN=150+5;
    int N,k,mod;
    inline int add(int x) {return x>=mod?x-mod:x;}
    inline void upd(int &x,int y) {x+=y; if(x>=mod) x-=mod;}
    namespace sub0 {
    	int dp[MAXN][MAXN];
    	int sol(int n) {
    		memset(dp,0,sizeof(dp));
    		for(int i=0;i<=k;++i) dp[0][i]=1;
    		for(int i=1;i<=n;++i) {
    			int R=n-i+1;
    			for(int j=1;j<=R;++j) upd(dp[i][j-1],dp[i-1][j]);
    			for(int j=0;j<R&&j<=k;++j) upd(dp[i][j],dp[i-1][0]);
    		}
    		return dp[n][0];
    	}
    	int sol() {
    		k>>=1;
    		return (ll)sol(N>>1)*sol((N+1)>>1)%mod;
    	}
    }
    namespace sub1 {
    	int dp[MAXN][MAXN][MAXN];
    	int sol() {
    		int n=(N+1)>>1,m=N-n;
    		k>>=1;
    		for(int i=0;i<=n;++i) {
    			dp[0][i][k]=1;
    			for(int j=k-1,r=1;j>=0;--j) {
    				dp[0][i][j]=r;
    				r=add(r<<1);
    			}	
    		}
    		for(int i=1;i+k<=m;++i) {
    			int R=n-i+1;
    			for(int j=1;j<=R;++j) for(int h=0;h<i+k;++h) if(dp[i-1][j][h]) {
    				upd(dp[i][j-1][0],dp[i-1][j][h]);
    				if(j+h<2*k+2) upd(dp[i][j-1][h+1],dp[i-1][j][h]);
    			}
    			for(int j=0;j<R;++j) for(int h=0;h<i+k;++h) if(dp[i-1][0][h]) {
    				upd(dp[i][j][0],dp[i-1][0][h]);
    				upd(dp[i][j][h+1],dp[i-1][0][h]);
    			}
    		}
    		for(int i=m-k+1;i<=n;++i) {
    			int R=n-i+1;
    			for(int j=1;j<=R;++j) for(int h=0;h<=m;++h) if(dp[i-1][j][h]) {
    				upd(dp[i][j-1][h],dp[i-1][j][h]);
    			}
    			for(int j=0;j<R;++j) for(int h=0;h<=m;++h) if(dp[i-1][0][h]) {
    				upd(dp[i][j][h],dp[i-1][0][h]);
    			}
    		}
    		int an=0;
    		for(int h=0;h<=m;++h) upd(an,dp[n][0][h]);
    		return an;
    	}
    }
    int main() {
    	rd(N),rd(k),rd(mod);
    	if(~k&1) printf("%d
    ",sub0::sol());
    	else printf("%d
    ",sub1::sol());
    	return 0;
    }
    
  • 相关阅读:
    BZOJ 1565: [NOI2009]植物大战僵尸
    BZOJ 1617: [Usaco2008 Mar]River Crossing渡河问题
    BZOJ 2820: YY的GCD
    数论模版-欧拉函数、莫比乌斯函数和素数
    BZOJ 2818: Gcd
    BZOJ 1615: [Usaco2008 Mar]The Loathesome Hay Baler麻烦的干草打包机
    BZOJ 1614: [Usaco2007 Jan]Telephone Lines架设电话线
    BZOJ 1613: [Usaco2007 Jan]Running贝茜的晨练计划
    BZOJ 1612: [Usaco2008 Jan]Cow Contest奶牛的比赛
    Unity5.3.4版本打包APk,安卓识别不了 Application.systemLanguage
  • 原文地址:https://www.cnblogs.com/ljzalc1022/p/13274654.html
Copyright © 2011-2022 走看看