LightOJ - 1102 Problem Makes Problem

来源:互联网 发布:java项目需求文档模板 编辑:程序博客网 时间:2024/06/05 14:41

题目分析

这道题主要利用了隔板法,那么如何使用呢??对于这个问题来说我们可以这样做,我们将从n个数中选取k个部分,因为里面有些部分可能为0,那么我们可以让每个部分至少为1,那么我们直接让原来的n加上k即可,这样就相当于在n+k个1数组成的n+k-1个空子中插入k-1隔板,那么这样就很明显了,直接求逆元然后处理一下可过,本来想把n的每个阶乘的值求出来没想到超空间了,于是老老实实不打表了。

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;#define LL long longconst int maxn = 2e6+100;const int mod = 1000000007;LL f[maxn];void exgcd(LL a, LL b, LL &x, LL &y){    if(!b) x = 1LL, y = 0LL;    else{        exgcd(b, a%b, y, x);        y -= x*(a/b);    }}void init(){    f[0] = 1;    for(int i = 1; i < maxn; i++)        f[i] = (f[i-1]*i)%mod;}LL inv(LL n){    LL x, y;    exgcd(n, mod, x, y);    return (mod + x%mod)%mod;}int main(){    init();    int T, n, k;    scanf("%d", &T);    for(int kase = 1; kase <= T; kase++){        scanf("%d%d", &n, &k);        printf("Case %d: %lld\n", kase, f[n+k-1]*inv(f[n]*f[k-1]%mod)%mod);    }    return 0;}

还有一种利用费马小定理,当p为素数是,ap2==a1(modp),这样之后直接快速幂即可,给出代码。

#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>using namespace std;#define LL long longconst int maxn = 2e6+100;const int mod = 1e9+7;LL f[maxn];void init(){    f[0] = 1;    for(int i = 1; i < maxn; i++)        f[i] = (f[i-1]*i)%mod;}LL quick_pow(LL a, LL b){    LL ans = 1;    while(b){        if(b&1) ans = (ans*a)%mod;        b >>= 1;        a = (a*a)%mod;    }    return ans;}LL solve(int n, int k){    return f[n]*quick_pow(f[n-k]*f[k]%mod, mod-2)%mod;}int main(){    init();    int T, n, k;    scanf("%d", &T);    for(int kase = 1; kase <= T; kase++){        scanf("%d%d", &n, &k);        printf("Case %d: %lld\n", kase, solve(n+k-1, k-1));    }    return 0;}
0 0
原创粉丝点击