ソリューションP3176 [[HAOI2015]デジタル文字列分割]

水溶液...

道路という問題は私のビットは無知やって、気持ちは完全に高齢者へのアイデアを言うに従ったものです


\(最初\)

まず、質問の意味を理解する必要があります。はい、これが最初のステップです。

私の区のタイトルが小さなポットあるとすると\(f_4 = 5 \ land m = 2 \)\(5 \)分割メソッド

\ [(4 =)1 + 1 + 1 + 1 = 1 + 1 + 2 = 1 + 2 + 1 = 2 + 1 + 1 = 2 + 2 \]

そうです、質問の意味は確かに正しいです。これは、\(1-m \)の自然数を使用して数を分割することです。また、数を異なる順序で分割する方法でもあるため、\(dp \)を検討できます。オフ

\(p \)の場合、

\ [p = 1 +(p-1)= 2 +(p-2)……+ m +(pm)\]

したがって、上記の\(m \)分割では、\(i \)分割によって提供されるカテゴリ数は\(f_ {pi} \)であることがわかります。それぞれの場合について、位置を切り替えないでください。計算して、例で遊んですべてのスキームが計算されたことを確認し、位置を交換して重みを計算できます(これが順列と組み合わせが常に簡単に計算できる理由です

だから最初の結論があります:

\ [f_p = \ sum_ {i = 1} ^ {m} f_ {pi} \]

これは少し考えるべきです-この質問はマトリックスです

\(秒\)

次表情\(G \) ギブ\(g_i \)別の定義:最初から文字列\(1 \)ビット\(DP \)最初に\(I \)回答ビット、我々が言うことです要件は\(g_n(n = strlen(S))\)

上記の最初の結論により、\(f \)を行列として表現できることがわかりました

転送行列が\(A \)の場合、\(g_i = A ^ {a_1 + a_2 +…+ a_k} = A ^ {a_1} * A ^ {a_2} *…* A ^ {a_k} \)(ここに\(a_k \)\(1 \)から\(i \)までの数です

したがって、再配布法は発見の波を乗り越えました\(g_i = \ sum_ {j = 0} ^ {i-1} g_j * A ^ {S _ {(j + 1)…i}} \)、そしてこのことについて\( A ^ {S _ {(j + 1)…i}} \)、最初に前処理できます\(A_ {i、j} \)\(jei(\ text {つまりis} j * 10 ^ i)を意味します\)転送行列。前処理は、最初に得られた結論によって処理できます。

したがって、\(g_i \)行列の波(md行列)を実行します

\(第3\)

コア部は、これらのトップ、最後に求め当然である\(G_N \) および\(ANS \)位置\((1、M)\ )

残りの詳細は、(コードでコードを見ることができます\(F \)テキストの代わりに\(G \) ):

#include<bits/stdc++.h>
using namespace std;

const int mod=998244353;

char ch[501];
int n,m;

struct node
{
	int a[6][6];
}f[501],A[501][10],zero;

node operator * (node x,node y)
{
	node tmp=zero;
	for(register int i=1;i<=m;++i)
		for(register int j=1;j<=m;++j)
			for(register int k=1;k<=m;++k)
				(tmp.a[i][j]+=1ll*x.a[i][k]*y.a[k][j]%mod)%=mod;
	return tmp;
}
node operator + (node x,node y)
{
	node tmp=zero;
	for(register int i=1;i<=m;++i)
		for(register int j=1;j<=m;++j)
			tmp.a[i][j]=(x.a[i][j]+y.a[i][j])%mod;
	return tmp;
}

int main()
{
	cin>>ch+1>>m;
	n=strlen(ch+1);
	for(register int i=1;i<=m;++i)
		for(register int j=1;j<=m;++j)
			zero.a[i][j]=0;
	for(register int i=1;i<=m;++i)
		A[0][0].a[i][i]=A[0][1].a[i][m]=1;
	for(register int i=1;i<m;++i)
		A[0][1].a[i+1][i]=1;
	for(register int i=2;i<=9;++i)
		A[0][i]=A[0][i-1]*A[0][1];
	for(register int i=1;i<=n;++i)
	{
		A[i][0]=A[0][0];
		A[i][1]=A[i-1][9]*A[i-1][1];
		for(register int j=2;j<=9;++j)
			A[i][j]=A[i][j-1]*A[i][1];
	}
	f[0].a[1][m]=1;
	for(register int i=1;i<=n;++i)
	{
		node tmp=A[0][ch[i]-'0'];
		for(register int j=i-1;~j;--j)
		{
			f[i]=f[i]+(f[j]*tmp);
			if(j) tmp=A[i-j][ch[j]-'0']*tmp;
		}
	}
	cout<<f[n].a[1][m]<<endl;
	return 0;
}

おすすめ

転載: www.cnblogs.com/ALANALLEN21LOVE28/p/12675369.html