PTA 礼尚往来(递推)

7-1 礼尚往来 (10分)

吉哥还是那个吉哥,那个江湖人称“叽叽哥”的基哥。每当节日来临,女友众多的叽叽哥总是能从全国各地的女友那里收到各种礼物。有礼物收到当然值得高兴,但回礼确是件麻烦的事!无论多麻烦,总不好意思收礼而不回礼,那也不是叽叽哥的风格。现在,即爱面子又抠门的叽叽哥想出了一个绝妙的好办法:他准备将各个女友送来的礼物合理分配,再回送不同女友,这样就不用再花钱买礼物了!假设叽叽哥的n个女友每人送他一个礼物(每个人送的礼物都不相同),现在他需要合理安排,再回送每个女友一份礼物,重点是,回送的礼物不能是这个女友之前送他的那个礼物,不然,叽叽哥可就摊上事了,摊上大事了…现在,叽叽哥想知道总共有多少种满足条件的回送礼物方案呢?

输入格式:

输入数据第一行是个正整数T,表示总共有T组测试数据(T <= 100); 每组数据包含一个正整数n,表示叽叽哥的女友个数为n( 1 <= n <= 100 )。

输出格式:

请输出可能的方案数,因为方案数可能比较大,请将结果对1000000007 取模后再输出。(提示:在递推过程中,不断求余防止数据太大导致数据溢出。) 每组输出占一行。

输入样例:

3
1
2
4

输出样例:

0
1
9

解题

  1. 这题不要盲目去解,一开始我就是这样,结果太复杂了,还写不出通项式,后来重新分析发现是个递推题。
  2. 设dp[n] 就表示n个人的方案
  3. 如下图,共有n个人,第一个位置(A)给除A以外的(n - 1) 人中的其中一人,则可有(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],综上有:
  4. 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;
}

猜你喜欢

转载自blog.csdn.net/qq_45349225/article/details/109434418
PTA
今日推荐