RPG的错排【错排公式+组合数学】

版权声明:https://blog.csdn.net/qq_41730082 https://blog.csdn.net/qq_41730082/article/details/85228517

题目链接


  要其中一半一下的数错排即可,那么就是我们累加一遍错的排序及其出现的组合数即可,

  那么,我们只需要知道怎么求错排的数的对应情况,及可能即可了:
  递推错排公式:将n个错排数记为f[n]。将n中的第1个排错,假设放在第k个位置,就有n-1种放法。那么第k个可以放在第1个位置,剩下的还有n-2个进行错排,为f[n-2];若第k个不放在第1个位置,则还有n-1个需要错排,为f[n-1]。因此得到错排数公式:f[n]=(n-1)*(f[n-1]+f[n-2]),其中f[0]=0,f[1]=0,f[2]=1。


#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <unordered_set>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxN = 28;
int N, mid;
ll f[maxN], ans, jiecheng[maxN];
void pre_did()
{
    f[0] = f[1] = 0;    //当只有0、1的情况的时候不存在错误的排序的可能,所以就是0
    f[2] = 1;   //错误的排序的存在可能
    jiecheng[0] = jiecheng[1] = 1;
    jiecheng[2] = 2;
    for(int i=3; i<maxN; i++)
    {
        f[i] = (i - 1) * (f[i-1] + f[i-2]);
        jiecheng[i] = jiecheng[i-1] * i;
    }
}
ll Cal(int down, int up)
{
    ll ans = 1;
    for(int i=down; i>=down - up + 1; i--) ans *= i;
    for(int i=up; i>1; i--) ans /= i;
    return ans;
}
int main()
{
    pre_did();
    while(scanf("%d", &N) && N)
    {
        mid = N/2;  ans = 0;
        for(int i=0; i<=mid; i++)
        {
            ans += Cal(N, i) * f[i];    //全都答对时的f[0]==0,会丢失一个答案
        }
        printf("%lld\n", ans + 1);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41730082/article/details/85228517
今日推荐