Lucas&ExLucas

Posted Heey

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Lucas&ExLucas相关的知识,希望对你有一定的参考价值。



Lucas:


公式:


C(n,m)%mod=C(n%mod,m%mod)*C(n/mod,m/mod)


需要保证mod为质数
证明省..

解决:
前面部分可以根据

直接求出 

后面部分就继续递归

#include<bits/stdc++.h>
using namespace std;
const int N=1e5;
long long n,m,mod,fac[N];
void init()
{
    int i;
    fac[0] =1;
    for(i =1; i <= mod; i++)
        fac[i] = fac[i-1]*i % mod;
}
long long q_pow(long long a, long long b)
{
    long long  ans =1;
    while(b)
    {
        if(b &1)  ans=ans*a%mod;
        b>>=1;
        a=a*a%mod;   
    }
    return  ans;
}
long long C(long long n, long long m)
{
    if(m > n)  return 0;
    return  fac[n]*q_pow(fac[m]*fac[n-m],mod-2) % mod;
}

long long Lucas(long long n, long long m )
{
    if(m==0)  return 1;
    return(C(n%mod,m%mod)*Lucas(n/mod m/mod))%mod;
}
int main()
{
    freopen("a.in","r",stdin);
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%lld%lld%lld", &n, &m, &mod);
        init();
        printf("%lld\\n",Lucas(n, m));
    }
    return 0;
}
View Code

 

 

 


 EX Lucas


解决mod不为质数的情况
我们先要求C(n,m)%mod
看到这个形式 我们可以考虑用中国剩余定理来求解
但是CRT也需要mod两两互质
怎么办?
我们把mod拆开modi=ai为质数,表示多个幂相乘

这样modi的两两互质 可以用CRT了
现在就可以 求出C(n,m)%modi 然后CRT合并
但是现在modi 虽然ai是质数 但却不是质数 

依然不能用Lucas求解(Lucas需要保证mod质数)

现在考虑C(n,m)%modi(modi不为质数) 怎么求?
我们把C(n,m)变成如果我们能求出a=n!%modi,b=m!%modi,c=(n-m)%modi

那么最后答案就是a*inv(b)*inv(c)%modi

 

举个例子:

n=19,a=3,i=2
我们求n!%modi
(1*2*3*4*5*6*7*8*9*10*11*12*13*14*15*16*17*18*19)%modi
我们把它分成三部分
1. (1*2*4*5*7*8)*(10*11*13*14*16*17)
2. (3*6*9*12*15*18)=(3^6)*(1*2*3*4*5*6)
3. 19


我们可以发现一些规律
1 是一个以为周期的循环节 在%modi后的值是相同的

解决方法:找出循环值和次数(n/3^6) 快速幂求解
2 可以把(3^6)拿出来 可以代入上下抵消 剩下的部分是(n/a)! 变成同样的问题 可以继续递归解决

3 这是没有完成的一周期 我们暴力求得即可

 

#include<bits/stdc++.h>
using namespace std;

long long read()
{
    long long x=0,f=1;
    char ch=getchar();
    while(ch<\'0\'||ch>\'9\') {if(ch==\'-\') f=-1;ch=getchar();}
    while(ch>=\'0\'&&ch<=\'9\') {x=x*10+ch-\'0\';ch=getchar();}
    return x*f;
}
long long mod,n,m,w;

long long qpow(long long a,long long b,long long p)
{
    long long ans=1LL;
    while(a>0)
    {
        if(a&1) ans=(ans*b)%p;
        b=(b*b)%p;
        a>>=1;
    }
    return ans;
}

void exgcd(long long a,long long b,long long &x,long long &y)
{
    if(b==0) {x=1;y=0;return ;}
    exgcd(b,a%b,x,y);
    long long temp=x;
    x=y;
    y=temp-a/b*y;
}

long long inv(long long a,long long p)
{
    long long x,y;
    exgcd(a,p,x,y);
    x=(x%p+p)%p;
    if(!x) x=p;
    return x;    
}

long long Mul(long long n,long long pi,long long pk)
{
    if(!n) return 1LL;
    long long ans=1LL;
    if(n/pk) 
    {
        for(long long i=2;i<=pk;i++) if(i%pi) ans=(ans*i)%pk;
        ans=qpow(n/pk,ans,pk);
    }
    for(long long i=2;i<=n%pk;i++) if(i%pi) ans=(ans*i)%pk;
    return (ans*Mul(n/pi,pi,pk))%pk;
    
}

long long C(long long n,long long m,long long pi,long long pk)
{
    if(n<m) return 0;
    long long a=Mul(n,pi,pk),b=Mul(m,pi,pk),c=Mul(n-m,pi,pk);
    long long k=0;
    for(long long i=n;i;i/=pi) k+=i/pi;
    for(long long i=m;i;i/=pi) k-=i/pi;
    for(long long i=n-m;i;i/=pi) k-=i/pi;
    long long ans=((a*inv(b,pk)%pk*inv(c,pk)%pk)%pk*qpow(k,pi,pk))%pk;
    return ans*(mod/pk)%mod*inv(mod/pk,pk)%mod;//mod/pk对pk的逆元
    
}

long long Lucas(long long n,long long m)
{
    long long ans=0;
    long long x=mod;
    for(long long i=2;i<=x;i++)
    {
        long long pk=1;
        if(x%i==0) 
        {
            while(x%i==0) pk*=i,x/=i;
            ans=(ans+C(n,m,i,pk))%mod;
        }
    }
    return ans;
}

int main()
{
    freopen("a.in","r",stdin);
    
    mod=read();n=read();m=read();
    long long ans=1;
    for(int i=1;i<=m;i++) 
    {
        w=read();
        if(n<w) {printf("Impossible\\n");return 0;}
        ans=(ans*Lucas(n,w))%mod;
        n-=w;
        printf("%lld %lld\\n",n,ans);
    }
    printf("%lld\\n",ans);    
    return 0;
}
View Code

 

 

 


 

以上是关于Lucas&ExLucas的主要内容,如果未能解决你的问题,请参考以下文章

[模板] 数学基础:逆元/exGCD/exCRT/Lucas定理/exLucas

「狗屁不会」exlucas

Lucas定理

组合数取模&&Lucas定理题集

P4720 模板扩展卢卡斯定理/exLucas(无讲解,纯记录模板)

一个思考Exlucas时的错误思路和对CRT的一些理解