問題への解決策[P1313]係数を計算します

この質問は非常に裸の二項定理であります

それがあることは明らかである結果
[C ^ {分(N \
倍B ^ {N} \ \ ^ {M}、M)} _ {K}回\] まず\(^ {M} \ ) と\(B ^ {N}は\)言っても過言フラッシュパワーによって計算されます

しかし、我々は、(C ^ {分(N \ 、M)} _ {K} \) 比較実に

組成式ルック
\ [C ^ {M} _ {N} = \ FRAC {N!} {M!(NM)!} = \ Fracの{N(N-1)(N-2)\ cdots( N-M + 1)} {
cdots \ 1 \ times2 \ times3 \回回M \} \] この式は、私たちが逆になるように分母を乗算、除算器を直接法とすることができないことは明らかである参照

しかし、私は、これはそれを行う行う方法逆ではないでしょうか?

まず、高校の数学で何の逆ではありません、我々は金型を取る必要はありません。だから我々は、組み合わせたポイント数の計算にそれに取り掛かります。ここでの最大分母の数はモジュロ1000年ではありません。だから我々は、これら二つの数字について、分子程度ポイント数を列挙するために、その後の分母に最初の数のそれぞれを列挙し、することができます\(GCDを\) 最後に私たちができるようになるので、それは、数字の組み合わせであるため、分母は約に分割する\(1 \)を法原理等に応じて任意の時間を掛けに待機している場合

これは逆の使用を回避します

#include <bits/stdc++.h>
#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;
}

おすすめ

転載: www.cnblogs.com/Mark-X/p/11699330.html