AGC035E Develop

题目大意

有1~n共n个数,每次删掉x并把x-2和x+K加上,问可能的序列个数

n<=150

题解

这才叫集训队作业

比较正常的做法:https://www.cnblogs.com/Tiw-Air-OAO/p/11795339.html

由于比较naive没有想出来,于是搞了另一种做法

把x向x-2和x+K连边,则一个删除序列满足条件当且仅当导出子图中无环(按拓扑序删就可以了)

K是偶数很简单,按奇偶分开就变成不能选连续的K/2+1个,随便dp

考虑K是奇数的情况

设K=7,则所有不合法方案的必然包含以下子串(?表示任意o表示选择):

ooooooooo

o?ooooooo?o

o?o?ooooo?o?o

o?o?o?ooo?o?o?o

按奇偶分开,就是奇/偶上连续一段和中间偶/奇的连续一段

很轻松的想到设f[i][j][k]表示放到i奇数位连续j个偶数位连续k个的方案,然后在中间连续段的后一位判断

这样有个问题,后面的部分无法判断,举个栗子

o?o?o?ooo?o?o?o

在ooo后的?处判断不选,那么接下来的三个o位置上不能同时选

考虑再加两维来表示奇/偶接下若干位不能同时选,这样是n^5的,考虑优化

可以发现ooo?无论怎样接(连续段+间隔)后面的长度都为K+2,而在至多K-2位置上就有一个不能选的,所以不会产生新的限制(不可能在?后面跳一位再选,两个空位会把前面的阻断)

记录连续选个数的意义就是为了产生限制,而现在不可能产生限制,所以就没有记的必要了

所以设f[i][j][k][0/1][0/1]表示放了i个,奇/偶 连续j/k个 或 接下来的j/k个不能同时选

转移讨论一下即可

code

#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define add(a,b) a=((a)+(b))%mod
#define ll long long
//#define file
using namespace std;

ll f[151][151][151][2][2],g[151][151],ans;
int n,m,mod,i,j,k,l,p1,p2,I,J,K,L,P1,P2,s;

ll qpower(ll a,int b) {ll ans=1;while (b) {if (b&1) ans=ans*a%mod;a=a*a%mod;b>>=1;} return ans;}

int main()
{
	#ifdef file
	freopen("agc035E.in","r",stdin);
	#endif
	
	scanf("%d%d%d",&n,&m,&mod);
	if (m==n) {printf("%lld
",qpower(2,n));return 0;}
	
	if (!(m&1))
	{
		g[0][0]=1;
		fo(i,1,n)
		{
			fo(j,0,m/2)
			{
				if (j<m/2) add(g[i][j+1],g[i-1][j]);
				add(g[i][0],g[i-1][j]);
			}
		}
		
		j=k=0;
		fo(i,0,m/2) add(j,g[(n+1)/2][i]),add(k,g[n/2][i]);
		printf("%lld
",1ll*j*k%mod);
	}
	else
	{
		f[0][0][0][0][0]=1;
		fo(i,1,n)
		{
			fo(j,0,i-1)
			{
				fo(k,0,i-1)
				{
					fo(p1,0,1)
					{
						fo(p2,0,1)
						if (f[i-1][j][k][p1][p2])
						{
							fo(s,0,1)
							{
								if (s) //yes
								{
									if (i&1)
									{
										K=k,P2=p2;
										if (!p1) J=j+1;
										else
										{if (j==1) continue; else J=j-1,P1=1;};
									}
									else
									{
										J=j,P1=p1;
										if (!p2) K=k+1;
										else
										{if (k==1) continue; else K=k-1,P2=1;};
									}
								}
								else //no
								{
									if (i&1)
									{
										if (p1 || p2 || k<m/2+2 || !j)
										J=0,P1=0,K=k,P2=p2;
										else
										{
											if (j>=m/2+1) continue;
											J=0,P1=0,K=m/2+1-j,P2=1;
										}
									}
									else
									{
										if (p2 || p1 || j<m/2+2 || !k)
										K=0,P2=0,J=j,P1=p1;
										else
										{
											if (k>=m/2+1) continue;
											K=0,P2=0,J=m/2+1-k,P1=1;
										}
									}
								}
								add(f[i][J][K][P1][P2],f[i-1][j][k][p1][p2]);
							}
						}
					}
				}
			}
		}
		
		fo(j,0,n)
		{
			fo(k,0,n)
			{
				fo(p1,0,1)
				{
					fo(p2,0,1)
					if (f[n][j][k][p1][p2] && !((!p1 && !p2 && ((n&1) && j>m/2+1 || !(n&1) && j>m/2)) && (!(n&1) && k>m/2+1 || (n&1) && k>m/2)))
					add(ans,f[n][j][k][p1][p2]);
				}
			}
		}
		printf("%lld
",ans);
	}
}
原文地址:https://www.cnblogs.com/gmh77/p/12829670.html