FZU 2282 错排问题dp

来源:互联网 发布:淘宝钻级店铺转让 编辑:程序博客网 时间:2024/06/08 15:39

题意:

题目链接:http://acm.fzu.edu.cn/problem.php?pid=2282
求1~n的全排列a中,a[i]==i的位置数目>=k的方案数有多少。


思路:

基础错排dp,与HDU 2049几乎完全一样,多了一个前缀和的操作。


代码:

#include <cstdio>using namespace std;typedef long long LL;const int MAXN = 1e4 + 10;const LL MOD = 1e9 + 7;LL dp[MAXN], fac[MAXN], inv[MAXN];LL pow_mod(LL a, LL n) {    LL res = 1;    while (n) {        if (n & 1) res = res * a % MOD;        a = a * a % MOD;        n >>= 1;    }    return res;}void init() {    fac[0] = inv[0] = 1;    for (int i = 1; i <= 10000; i++) {        fac[i] = fac[i - 1] * i % MOD;        inv[i] = pow_mod(fac[i], MOD - 2);    }}LL C(int n, int k) {    return fac[n] * inv[k] % MOD * inv[n - k] % MOD;}int main() {    //freopen("in.txt", "r", stdin);    init();    dp[0] = 1;    for (int i = 1; i <= 10000; i++) {        LL t = ((i - 1) % MOD + MOD) % MOD;        dp[i] = (dp[i - 1] * t) % MOD;        if (i >= 2) {            dp[i] = (dp[i] + t * dp[i - 2] % MOD) % MOD;        }    }    int T;    scanf("%d", &T);    while (T--) {        int n, k;        scanf("%d%d", &n, &k);        LL ans = 0;        for (int i = 0; i <= n - k; i++) {            LL tmp = C(n, i) * dp[i] % MOD;            ans = (ans + tmp) % MOD;        }        printf("%lld\n", ans);    }    return 0;}
原创粉丝点击