题解 P1313 【计算系数】

这道题是一道非常裸地二项式定理

结果很明显就是
\[ C^{min(n,m)}_{k} \times a^{m} \times b^{n} \]
首先\(a^{m}\)\(b^{n}\)用快速幂计算不多说

但我们\(C^{min(n,m)}_{k}\)比较难搞

先看组合数的公式
\[ C^{m}_{n} = \frac{n!}{m!(n-m)!} = \frac{n(n-1)(n-2) \cdots (n-m+1)}{1\times2\times3\times\cdots\times m} \]
看到这个式子很明显以为要取模所以我们不能直接用除法,要变成乘分母的逆元

但是我不会逆元这该怎么办办呢?

首先在高中数学里是没有逆元的,我们也不需要取模。所以我们在计算组合数的时候就是先去约分。在这里分母上的一个数最大是1000不用取模。所以我们可以先枚举分母上的每一个数字,再枚举分子上的一个数字进行约分,约这两个数的\(GCD\)。因为是组合数,所以最后我们一定可以约分成分母是\(1\)的情况这个是候在根据随时取模原理做乘法就好

这样就可以避免使用逆元

#include 
#define LL long long
using namespace std;


const int N = 1e6+5;
const LL mod = 10007;
LL a,b,k,n,m,result = 1,t[N];


inline LL gcd(LL a,LL b) {return !b?a:gcd(b,a%b);}

inline LL ksm(LL a,LL b)
{
    register LL ans = 1;
    while(b)
    {
        if(b & 1) ans = (ans * a) % mod;
        a = (a * a) % mod;
        b >>= 1;
    }
    return ans % mod;
}


int main()
{
    cin >> b >> a >> k >> n >> m;
        
    result = (result * ksm(b,n)) % mod;
    result = (result * ksm(a,m)) % mod;
    
    n = min(n,m);
    
    for(register int i = 1,j = k - n + 1;i <= n;i ++,j ++) t[i] = j;
    
    for(register int i = 2;i <= n;i ++)
    {
        register LL x = i,y;
        for(register int j = 1;j <= n;j ++)
        {
            if(x > t[j]) y = gcd(x,t[j]);
            else y = gcd(t[j],x);
            if(y == 1) continue;
            x /= y; t[j] /= y;
            if(x == 1) break;
        }
    }
    
    for(register int i = 1;i <= n;i ++) result = (result * t[i]) % mod;
    
    cout << result << endl;
}

你可能感兴趣的:(题解 P1313 【计算系数】)