【質問解決】Luogu P4838 P兄弟がコードをクラック

移動:自分のブログ

トピック

Luogu 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