zoukankan      html  css  js  c++  java
  • 卢卡斯定理 刷题记录

    定理内容

    $C^b_a(modp)=prod_{i=0}^nC_{ai}^{bi}$

    其中 $a=sum_{i=0}^na_i*p^i$,$b=sum_{i=0}^nb_i*p^i$

    • 当p很小时,要计算较大的组合数可以考虑使用该定理:$C^b_amodp=C^{b/p}_{a/p}*C^{bmodp}_{amodp}$
    • 然后就降到O(p),此时用组合数的定义和逆元算就是O(p)了

    证明

    bzoj 3260: 跳

    • 从(0,0)出发在二维坐标上移动,最后到达(n,m)点,问花费的最小代价
    • C(x,y)=C(x,y-1)+C(x-1,y)    其中C(x,y)为(x,y)点花费的代价,C(0,0)为1
    • 容易看出杨辉三角...
    • 打个表发现贪心,如果n>m,直接先向上走n步,再向右走到目的地
    • 然后发现那个组合数连加有个公式。。。最后就是这样
    • 用到卢卡斯定理是因为m,n特别大
    • 代码:
       1 #include <bits/stdc++.h>
       2 #define nmax 1000
       3  
       4 using namespace std;
       5 typedef long long ll;
       6 const ll mn = 1000000007;
       7  
       8 ll fp(ll x, ll y){
       9     if(x == 1) return y;
      10     ll t = fp(x/2, y);
      11     if(x&1) return ( (t*t % mn)*y ) % mn;
      12     else return (t*t) % mn;
      13 }
      14  
      15 ll getinv(ll x){
      16     ll ans = fp(mn-2, x);
      17     return ans;
      18 }
      19  
      20 ll gc(ll b, ll e){
      21     ll ans = 1;
      22     for (ll i=b; i<=e; i++) { ans *= i; ans %= mn; }
      23     return ans;
      24 }
      25  
      26 ll cc(ll a, ll b){
      27     return gc(a-b+1, a) * getinv( gc(1,b) ) % mn;
      28 }
      29  
      30 int main(){
      31     ll n, m, a, b, ans, c, d, e, f;
      32     cin >> a >> b;
      33     n = max(a, b);
      34     m = min(a, b);
      35     ans = n % mn;  //C(m , n+m+1)
      36     a = n+m+1, b = m;  //c(a,b)
      37     c = a/mn; 
      38     d = b/mn;
      39     e = a%mn;
      40     f = b%mn;
      41     ans += cc(c, d) * cc(e,f) % mn;
      42     ans %= mn;
      43     cout << ans << endl;
      44     return 0;
      45 }
      quq
  • 相关阅读:
    python2
    python1
    jmeter基础使用
    LoadRuuner资源监控
    UI自动化
    MYSQL增删改查添加外键
    DW网页代码笔记
    Linux常用命令(常用)
    Linux常用命令大全(全全全!!!)
    第十二章 : shell 环境
  • 原文地址:https://www.cnblogs.com/jiecaoer/p/11821187.html
Copyright © 2011-2022 走看看