【NOIPシミュレーション試験]:洞窟(DP +高速電力)

タイトル説明

セダムは洞窟に行ってきました。彼はと遊ぶためにここと姉妹でなければなりませんでした。洞窟は、リング、$ $ n番目のノードの合計、彼は最初に$ 0 $ノード番号、私は$私は彼がどちらの方向のステップに行くことができます$二モバイル$ $です。行うには、他の重要なことがあるので、彼は正確に$ M $回の後に戻って$ 0 $ノード番号に移動して残して、そして今、彼はどのくらいのプログラム番号、金型の$ 1E9 + 7 $知りたいしなければなりません。(二つのオプションは、異なるとみなされる場合に限り、位置は、少なくとも特定のステップセダム後ここで異なります)


入力形式

ライン二つの整数その表面場合は意味$ N $、$ Mは$、。


出力フォーマット

ラインアナログプログラムの$ 1E9 + 7 $の数を表す整数。


サンプル

サンプル入力1:

4 6

出力例1:

0

サンプル入力2:

707 185547

サンプル出力2:

588828156


データ範囲とヒント

$ 20 \%の$データの場合は、$ m個の\ leqslant 20 $。
$ 60 \%の$データの場合は、$ m個の\ leqslant $ 1,000。
$ \ 100%の$データ、$ Mの\のleqslantの1E9、nの \ leqslant $ 1,000。


問題の解決策

この質問は、私は、変更されている、間違っている質問の元のタイトルの意味です。

$ 40 \%の$アルゴリズム:

直接出力$ 0 $千万人、と私はショックを受けたが、実際に多くのポイントを持っている〜

時間の複雑さ:$ \シータ(1)$。

$ 0 $のポイント:スコアを期待しています。

実際のスコア:$ $ 40ポイント。

$ 60 \%の$アルゴリズム:

提供$のDP [I] [J] $ $ $ $ I $ Jにプログラムステップの数を表し、その後容易に状態遷移方程式を挙げることができる:$のDPを[I] [J] = DP [1- 1] [じ] + DP [I-1] [J + I] $。

時間複雑:$ \シータ(n回mを\)$。

期待はスコア:$ $ 60点。

実際のスコア:$ $ 60点が(「アルゴリズム」において上記で$ 80 $をサブすることができます)。

$ \ 100%の$アルゴリズム:

我々は唯一の前処理工程$の$ nのケースを見つけることができます前に、その後、$ \は\ lceil \ FRAC {M} {n}は\右\ rceil $フラッシュパワーによって回、$ m個の\のmod nを$手順、さらに暴力を残した治療仕上げは、時間の複雑さが許可されていませんか?巡回行列がすごい、感情的なプッシュ右へ数歩として理解することができます。

時間は複雑:$ \シータ(N ^ 2 \回\メートルを記録)$。

期望得分:$100$分。

实际得分:$100$分。


代码时刻

#include<bits/stdc++.h>
using namespace std;
long long n,m;
long long dp[1001][1001];
long long wzc[1001],flag[1001],ans[1001];
void matrix1()
{
	for(long long i=0;i<n;i++)flag[i]=ans[i],ans[i]=0;
	for(long long i=0;i<n;i++)
		for(long long j=0;j<n;j++)
			ans[(i+j)%n]=(ans[(i+j)%n]+flag[i]*wzc[j]%1000000007)%1000000007;
}
void matrix2()
{
	for(long long i=0;i<n;i++)flag[i]=wzc[i],wzc[i]=0;
	for(long long i=0;i<n;i++)
		for(long long j=0;j<n;j++)
			wzc[(i+j)%n]=(wzc[(i+j)%n]+flag[i]*flag[j]%1000000007)%1000000007;
}
int main()
{
	scanf("%lld%lld",&n,&m);
	dp[0][0]=1;
	for(long long i=1;i<=n;i++)
		for(long long j=0;j<n;j++)
		{
			if((j-i+n)%n==(j+i)%n)dp[i][j]=dp[i-1][(j+i)%n];
			else dp[i][j]=(dp[i-1][(j-i+n)%n]+dp[i-1][(j+i)%n])%1000000007;
		}
	for(long long i=0;i<n;i++)
		wzc[i]=dp[n][i];
	ans[0]=1;
	long long bs=m/n;
	while(bs)
	{
	    if(bs&1)matrix1();
	    matrix2();
	    bs>>=1;
	}
	bs=m%n;
	for(long long i=0;i<n;i++)
		dp[0][i]=ans[i];
	for(long long i=1;i<=bs;i++)
		for(long long j=0;j<n;j++)
		{
			if((j-i+n)%n==(j+i)%n)dp[i][j]=dp[i-1][(j+i)%n];
			else dp[i][j]=(dp[i-1][(j-i+n)%n]+dp[i-1][(j+i)%n])%1000000007;
		}
	printf("%lld",dp[bs][0]);
	return 0;
}

rp++

おすすめ

転載: www.cnblogs.com/wzc521/p/11431071.html