弱校联盟#con3--概率(阶乘逆元打表)

List’s father morejarphone likes playing poker with List very much. Now List has a deck of playing card, consisting of a black cards and b red cards. List shuffles the cards randomly, puts them on the desk and tells morejarphone to do the following operations:
1. taking away one card randomly;
2. checking the color of it, if it is black, repeats the operations until he take a red one or there are no cards left, else stops.
Now List wants to know the mathematical expectation of the cards morejarphone takes away in total. To avoid the float number, you should multiply the answer by (a+b)! then mod 1e9+7. If morejarphone can’t take red card, output “List, are you kidding me?”.

%mod*A会先算乘呀。。我好智障啊。。。wa了那么多个小时???
博客里还没有逆元啊。。随便说一句。。
费马小定理知道a^(p-1) = 1(mod p)(p为素数)
那么a的逆元一定a^(p-2) 除非再mod下先后顺序不能改变,否则影响结果
然后阶乘逆元是前面的逆元乘起来 那从后往前退,就是
inv[n] = inv[(n+1)!]/inv[n+1] = inv[(n+1)!]*(n+1)

还有单纯递推逆元的话,不用每一个都快速幂求p-2次幂。。

void init()
{
    inv[1]=1;  
    for(int i=2; i<N; i++)  
        inv[i]=(mod-mod/i)*inv[mod%i]%mod;     
}
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
typedef long long LL;
const LL MOD = 1e9+7;
const int maxn = 1e6+10;

int T;
LL inv[maxn],Fac[maxn];

LL quipow(LL m,LL nn){
    LL ans = 1;
    while (nn){
        if (nn & 1)
            ans = (ans*m) % MOD;

        m = (m * m) % MOD;
        nn >>= 1;
    }
    return ans;
}

void init(){
    Fac[1] = 1;
    Fac[0] = 1;
    LL maxx = 1e6+2;
    for(int i = 2;i <= maxx;i++){
        Fac[i] = (Fac[i-1]*(long long)i)%MOD;
    }
    inv[maxx]=quipow(Fac[maxx],MOD-2);
    for(int i = maxx-1;i >= 0;i--){
        inv[i]=(inv[i+1]*(long long)(i+1))% MOD;
    }
    //cout << inv[0]<<endl;
}

void sov(){
    for(int i = 1; i <= T ; i++){
        long long  A,B;
        cin >>A >> B;
        printf("Case #%d:",i);
        if(B == 0){
            printf(" List, are you kidding me?\n");
            continue;
        }
        LL ans = (B * Fac[A+B-1]) % MOD ;
        for ( LL k = 1 ; k <= A ; k ++ ) {
            LL tmp = (B * Fac[A+B-k-1]) % MOD ;
            tmp = (tmp * Fac[A]) % MOD ;
            tmp = (tmp * inv[A-k]) % MOD ;
            tmp = (tmp * (k+1)) % MOD ;
            ans = (ans + tmp) % MOD ;
        }
        cout <<" "<<ans<<endl;
    }
}

int main(){
    init();
    scanf("%d",&T);
    sov();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值