• 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);
    	}
    }
    
  • 相关阅读:
    Office2007界面风格的绿色软件针式个人知识库管理系统[V3.5]
    Mentor工具简介
    Xilinx网站资源导读
    FPGA时钟问题的探讨汇总
    FPGA中竞争冒险问题的研究
    一些IC前端设计工具
    SPI协议简介
    USB接口定义
    TTL与CMOS电平的区别
    Synopsys工具简介
  • 原文地址:https://www.cnblogs.com/gmh77/p/12829670.html
Copyright © 2020-2023  润新知