7-1相互関係(10ポイント)
ジゲは今でもあのジゲ、「ちじげ」と呼ばれるジゲです。ガールフレンドが多いジジは、休日になるといつでも全国のガールフレンドから様々なプレゼントを受け取ることができます。贈り物を受け取ることは確かに喜びに値しますが、贈り物を返すことは確かに面倒です!どんなに面倒でも、プレゼントを受け取って返してくれないのはいつも恥ずかしいです。それはチチ兄弟のスタイルではありません。今、顔を節約し、けちなジジは素晴らしい方法を考え出しました:彼は各ガールフレンドからの贈り物を合理的に配布し、次にそれらを別のガールフレンドに送り返す準備ができているので、費やす必要はありません贈り物にお金!ジジのn人のガールフレンドがそれぞれ彼にギフトを贈り(各人が彼にギフトを贈る)、今度は彼が合理的な手配をしてから、各ガールフレンドにギフトを送る必要があるとします。ポイントは、返されるギフトはこのガールフレンドではないということです。私は前に彼に与えました、さもなければ、ジジは大したことになるでしょう...今、ジジは、合計で何種類の贈答計画を満たしているのか知りたいですか?
入力フォーマット:
入力データの最初の行は正の整数Tです。これは、テストデータのグループが合計T個あることを意味します(T <= 100)。データの各グループには正の整数nが含まれます。これは、のガールフレンドの数を意味します。ジジはn(1 <= n <= 100)です。
出力フォーマット:
解の数は比較的多い可能性があるため、可能な解の数を出力してください。1000000007を法として結果を出力してください。(ヒント:再帰の過程で、データが多すぎるためにデータがオーバーフローするのを防ぐために、残りを見つけ続けます。)出力の各グループは1行を占めます。
入力サンプル:
3
1
2
4
サンプル出力:
0
1
9
問題解決
- この質問を盲目的に解決しようとしないでください。最初はこのようでした。結果が複雑すぎて一般的な用語を書くことができませんでした。後で再分析したところ、再帰的な質問であることがわかりました。
- dp [n]がn人の計画を表すとします
- 下の図に示すように、合計n人です。A以外の(n-1)人の1人に最初の位置(A)を与えると、(n-1)の選択肢があります。 n-1人、n -2人が繰り返しを持っていると仮定します。つまり、すべてのn-1人が繰り返しを持っていると仮定します。つまり、F = Aの場合、n-1人に対してdp [n-1]スキームがあります。 、これが直接計算の場合である場合、Aが位置Fにある回数をカウントしていません。ここで、Aを位置Fに直接配置し、n-2の位置を残します。これらはすべて、n-2、つまりdp [n -2]、要約すると:
- dp [n] =(n-1)*(dp [n-1] + dp [n-2]);結果はpの剰余だけを取ります。
コード
#include <algorithm>
#include <iostream>
#include <string>
using namespace std;
typedef long long ll;
const int p = 1000000007;
const int maxn = 102;
ll dp[maxn];
int main() {
int T, n;
dp[1] = 0;
dp[2] = 1;
for (int i = 3; i < maxn; i++) {
dp[i] = (i - 1LL) * (dp[i - 1] + dp[i - 2]) % p;
}
cin >> T;
// for (int i = 1; i <= T; i++) {
// cout << i << " " << dp[i] << endl;
// }
while (T--) {
cin >> n;
cout << dp[n] << endl;
}
system("pause");
return 0;
}