全错排公式

链接:https://ac.nowcoder.com/acm/contest/9165/C
来源:牛客网

同学们的教室由于要作为考场,被要求将所有椅子搬到学校的仓库(不知道学校这样规定干嘛的/(ㄒoㄒ)/~~)
于是乎,同学们就开始忙碌起来,把自己的椅子都搬到学校的仓库了。
学校比较poor,每个同学只有一把椅子,而且同学们都比较憨,不认得自己的椅子(或者说椅子都长得一毛一样,没有人在上面乱涂乱画)
搬到仓库以后,仓库的管理员闲着无聊,就把椅子全部打乱了。
考试完了以后,同学们都不认得自己的椅子了,就只能随机的把它们搬回去。
用心险恶的仓库管理员想要所有同学们都搬不到自己原来的椅子,换句话说,每个同学都使用了别人的椅子,这样它就能达到某种目的(也许是为了好玩)
请你求出仓库管理员能达到目的概率,用分数表示

输入描述:

输入有多组测试用例,第一行输入t,表示用例个数
从第二行到第t+1行 输入为学生的人数n(1<=n<=20)

输出描述:

输出概率(用最简分数表示)
格式:(分子)/(分母)
示例1

输入

复制
2
1
2

输出

复制
0/1
1/2



首先你要先知道全错排公式p[n]=(n-1)(p[n-1]+p[n-2])
v[n]为n的阶乘
所以这个答案就是p[n]/v[n]


#include<iostream>
#include<algorithm>
#include<map>
using namespace std;
typedef long long ll;
const int maxn=1e5+100;
ll p[maxn];
ll z[maxn];
ll gcd(ll a,ll b){
    if(b==0){
        return a;
    }
    return gcd(b,a%b);
}
int main(){
    p[1]=1;
    for(int i=2;i<=20;i++){
        p[i]=p[i-1]*i;
    }
    z[1]=0;
    z[2]=1;
    for(int i=3;i<=20;i++){
        z[i]=(i-1)*(z[i-1]+z[i-2]); 
    }
    int t;
    cin>>t;
    while(t--){
        ll n;
        cin>>n;
        if(n==1){
            printf("0/1\n");
            continue;
        }
        ll d=gcd(p[n],z[n]);
        ll a=p[n]/d;
        ll b=z[n]/d;
        printf("%lld/%lld\n",b,a);
    }
}

 



posted @ 2020-11-30 00:10  哎呦哎(iui)  阅读(427)  评论(0编辑  收藏  举报