zoukankan      html  css  js  c++  java
  • [xdoj1158]阶乘求逆元(常用于求组合数)

    http://acm.xidian.edu.cn/problem.php?id=1158

     解题关键:此题注意将$sumlimits_{i = 0}^x {C_x^iC_y^{i + k}}$转化为$C_{x + y}^{x + k}$

    利用二项式定理,

    一方面,

    ${(1 + a)^y}{(1 + frac{1}{a})^x}$的${a^k}$项的系数,第一个二项式的${a^j}$的系数$C_y^j$,第二个二项式的${a^{ - i}}$系数为$C_x^i$,令$j - i = k$,$j = i + k$,即$sumlimits_{i = 0}^x {C_x^iC_y^{i + k}}$

    另一方面,

    ${(1 + a)^y}{(1 + frac{1}{a})^x} = {(1 + a)^{x + y}}{a^{ - x}}$,此时${a^k}$项的系数为$C_{x + y}^{x + k}$,得证。

    1、打表

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long  ll;
     4 const ll mod=1e9+7;
     5 ll x,y,k;
     6 ll fac[2000005],inv[2000005];
     7 
     8 ll mod_pow(ll x,ll n,ll mod){
     9     ll res=1;
    10     while(n){
    11         if(n&1) res=res*x%mod;
    12         n>>=1;
    13         x=x*x%mod;
    14     }
    15     return res;
    16 }
    17 
    18 ll Inv(ll x){
    19     return mod_pow(x,mod-2,mod);
    20 }
    21 
    22 int main(){
    23     fac[1]=1;
    24     for(int i=2;i<=2000000;i++) fac[i]=fac[i-1]*i%mod;//预处理一下,阶乘 
    25     inv[2000000]=mod_pow(fac[2000000],mod-2,mod);//Fac[N]^{MOD-2}
    26     for(int i=2000000-1;i>=0;i--) inv[i]=inv[i+1]*(i+1)%mod;
    27     
    28     
    29     while(~scanf("%lld%lld%lld",&x,&y,&k)){
    30         if(y==k)  printf("1
    ");
    31         else if(y<k)  printf("0
    ");
    32       //  else   printf("%lld
    ",fac[x+y]*inv(fac[x+k])%mod*inv(fac[y-k])%mod);
    33       else printf("%lld
    ",(fac[x+y]%mod*inv[x+k]%mod*inv[y-k]%mod+mod)%mod);
    34     }
    35     return 0;
    36 }

    2、打表+逆元实现

    为什么是$n{!^{mod  - 2}}$

    $n{!^{p - 2}}*n! = n{!^{p - 1}} = 1mod { m{ p;}}$(费马小定理)p为质数,此题中即为mod

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long  ll;
     4 const ll mod=1e9+7;
     5 ll x,y,k;
     6 ll fac[2000005],inv[2000005];
     7 
     8 ll mod_pow(ll x,ll n,ll mod){
     9     ll res=1;
    10     while(n){
    11         if(n&1) res=res*x%mod;
    12         n>>=1;
    13         x=x*x%mod;
    14     }
    15     return res;
    16 }
    17 
    18 ll Inv(ll x){
    19     return mod_pow(x,mod-2,mod);
    20 }
    21 
    22 int main(){
    23     fac[1]=1;
    24     for(int i=2;i<=2000000;i++) fac[i]=fac[i-1]*i%mod;//预处理一下,阶乘 
    25     //inv[2000000]=mod_pow(fac[2000000],mod-2,mod);//Fac[N]^{MOD-2}
    26     //for(int i=2000000-1;i>=0;i--) inv[i]=inv[i+1]*(i+1)%mod;
    27     
    28     
    29     while(~scanf("%lld%lld%lld",&x,&y,&k)){
    30         if(y==k)  printf("1
    ");
    31         else if(y<k)  printf("0
    ");
    32         else   printf("%lld
    ",fac[x+y]*Inv(fac[x+k])%mod*Inv(fac[y-k])%mod);
    33       //else printf("%lld
    ",(fac[x+y]%mod*inv[x+k]%mod*inv[y-k]%mod+mod)%mod);
    34     }
    35     return 0;
    36 }
  • 相关阅读:
    完成端口CreateIoCompletionPort编写高性能的网络模型程序
    offsetof的使用
    __attribute__
    nn_slow和nn_fast
    完成端口(Completion Port)详解(转)
    等待
    win8.1磁盘使用率100解决方法
    ubuntu 14.04 修改PS1提示符
    ubuntu14.04 开启root登陆
    Linux下彻底卸载LibreOffice方法
  • 原文地址:https://www.cnblogs.com/elpsycongroo/p/6809430.html
Copyright © 2011-2022 走看看