bzoj4417 [Shoi2013] Super Vaulting Matrices

When playing with hands, I looked for the law of transfer and found that it can be classified by parity. Points with different parities can be transferred in 3 adjacent rows, and points with the same parity cannot be transferred.

So for each line, record the prefix sum of the odd and even, so you can save the point of scanning the same line

Note that because it is a pairwise transfer, pay attention to distinguish 1->4 and 1->2 in 12->34. In order to avoid 3->4, separate 12->3 12->4 is required.

You can use 3 as the bridge 12->3->4, please write clearly and don’t mess up

Pay attention to the special judgment n=1


code:

#include<iostream>
#include<cstdio>
using namespace std;
#define HA 30011
int n,m,i,j,k,f[150][150],b[150],c[150][150],a[150],g[150][150];
int main()
{
	scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
{
	f[i][i]=1;	
}
for(i=1+n;i<=2*n;i++)
{
	if(i-n-1>=1)f[i][i-n-1]=1;
	if(i-n+1<=n)f[i][i-n+1]=1;
	f[i][i-n]=1;
}//下一个左边的转移 
for(i=1+n;i<=n*2;i++)
{
f[i][i]=1;	
}
for(i=1;i<=2*n;i++)
for(j=1;j<=n;j++)
{
if(j>1)f[i][j+n-1]+=f[i][j];
if(j<n)f[i][j+n+1]+=f[i][j];
	f[i][j+n]+=f[i][j];
}
//下一个右边的转移 
	a[1]=1;
	a[1+n]=a[2+n]=1;
	int lin=m/2;
lin--;
	while(lin)
	{
		if(lin&1)//答案转移上 
		{
			for(i=1;i<=n*2;i++)
			for(j=1;j<=n*2;j++)//n*2 to n*2
			{
				b[j]+=a[i]*f[i][j];	
				b[j]%=HA;		
			}			
		for(i=1;i<=2*n;i++)a[i]=b[i],b[i]=0;
		}
		lin/=2;
		for(i=1;i<=n*2;i++)
		for(j=1;j<=n*2;j++)	
		for(k=1;k<=n*2;k++)
		{
			c[i][k]+=f[i][j]*f[j][k];
			c[i][k]%=HA;		
		}		
		for(i=1;i<=2*n;i++)
		for(j=1;j<=2*n;j++)
		f[i][j]=c[i][j],c[i][j]=0;
	}
	if(m&1)
	printf("%d",(a[2*n]+(n==1?0:a[2*n-1]))%HA);
	else printf("%d",(a[n]+(n==1?0:a[n-1]))%HA);
}


Guess you like

Origin blog.csdn.net/haobang866/article/details/79248282