AcWing 230. 排列计数 错排问题

 

 代码如下:

#include <bits/stdc++.h>
// #define LOCAL
#define INF 0x3f3f3f3f3f3f3f3f
#define IOS ios::sync_with_stdio(false), cin.tie(0)
#define int long long
#define debug(a) cerr << #a << "=" << a << endl;
using namespace std;
const int mod = 1e9 + 7, N = 1e6;
int f[N + 2], fac[N + 2], inv[N + 2];
int qmi(int a, int k, int p){
    int ans = 1;
    while(k){
        if(k & 1)
            ans = ans * a % p;
        k >>= 1;
        a = a * a % p;
    }
    return ans;
}
void solve(){
    int n, m;
    scanf("%lld%lld", &n, &m);
    cout << fac[n] * inv[n - m] % mod * inv[m] % mod * f[n - m] % mod << '\n';
}

void init(){

    f[0] = f[2] = fac[0] = fac[1] = inv[0] = inv[1] = 1; //注意,元素个数为0时,是错排的
    fac[2] = 2, inv[2] = qmi(2, mod - 2, mod);
    for (int i = 3; i <= N; ++i){
        f[i] = (f[i - 1] + f[i - 2]) % mod * (i - 1) % mod;
        fac[i] = fac[i - 1] * i % mod;
        inv[i] = qmi(fac[i], mod - 2, mod);
    }
}
signed main(){
#ifdef LOCAL
    freopen("input.in", "r", stdin);
    freopen("output.out", "w", stdout);
#endif
    // IOS;
    init();
    int tt;
    scanf("%lld", &tt);
    while(tt--)
        solve();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值