【题解】洛谷P4838 P哥破解密码

前往:我自己搭建的博客

题目

洛谷P4838 P哥破解密码

题解

对于n<=1e7的数据,可以使用常规的动态规划。用f[i][0/1/2]分别表示长度为i,且以AA/A/B结尾的字符串的数量。可以得到状态转移方程:

f[i][0]=f[i-1][1] , f[i][1]=f[i-1][2] , f[i][2]=f[i-1][0]+f[i-1][1]+f[i-1][2]

对于大数据,使用矩阵优化。

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MOD=19260817;
int n;
struct matrix{ll s[5][5];}st,nxt;
inline matrix mul(matrix a,matrix b)
{
	matrix c; memset(c.s,0,sizeof(c.s));
	for(int i=1;i<=3;i++)
		for(int j=1;j<=3;j++)
			for(int k=1;k<=3;k++)
				c.s[i][j]=(c.s[i][j]+a.s[i][k]*b.s[k][j]%MOD)%MOD;
	return c;
}
inline matrix quick_pow(matrix a,ll b)
{
	matrix c;
	for(int i=1;i<=3;i++)for(int j=1;j<=3;j++) c.s[i][j]=(i==j);
	for( ;b;b>>=1)
	{
		if(b&1) c=mul(c,a);
		a=mul(a,a);
	}
	return c;
}
inline void pre()
{
	st.s[1][1]=0;st.s[2][1]=1;st.s[3][1]=1;
	nxt.s[1][1]=0;nxt.s[1][2]=1;nxt.s[1][3]=0;
	nxt.s[2][1]=0;nxt.s[2][2]=0;nxt.s[2][3]=1;
	nxt.s[3][1]=1;nxt.s[3][2]=1;nxt.s[3][3]=1;
}
inline void solve()
{
	pre(); nxt=quick_pow(nxt,n-1);
	st=mul(nxt,st);
	ll ans=(st.s[1][1]+st.s[2][1]+st.s[3][1])%MOD;
	printf("%lld\n",ans);
}
 
int main()
{
	int T; scanf("%d",&T);
	while(T--)
	{
		scanf("%d",&n);
		solve();
	}
	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/zjgmartin/article/details/108415600