zoukankan      html  css  js  c++  java
  • 【模板】扩展卢卡斯(学习笔记)

    洛咕

    (C_n^m mod p),(1≤m≤n≤10^{18}),(2≤p≤1000000),不保证p是质数.

    分析:对于模数不是质数,但是可以分解成几个质数的乘积(唯一分解定理)的情况,与古代猪文这道题有点类似.古代猪文中我们直接求出了原式分别模分解出的质数之后的值,然后把这些值用中国剩余定理(CRT)合并.本题也可以采取类似方法,假设(p=p_1^{c_1}p_2^{c_2}...p_k^{c_k})于是题目转化为了求(frac{n!}{m!(n-m)!} mod p_i^{c_i}),但值得注意的是(p_i^{c_i})是质数的幂,而非质数.

    现在我们来考虑如何求(frac{n!}{m!(n-m)!} mod p_i^{c_i}).因为模数不是质数,所以不能直接用逆元求,考虑是否能够把所有与(p_i^{c_i})不互质的数单独拎出来,对于(n!),提出一个数,总共有(frac{n}{p_i}),而剩下的能做贡献的只有([frac{n}{p_i}]!)(向下取整),对此进行递归求解即可.

    接下来考虑如何处理不是(p_i)的倍数的数,直接算肯定会超时,考虑它具有循环节的这一特点,每一个循环节的余数都相同,故只需处理一个循环节,其他循环节直接调用结果即可,可能最后还会有一小部分不构成完整循环节,这一部分可以直接暴算.

    #include<bits/stdc++.h>
    #define LL long long
    #define rg register
    using namespace std;
    inline LL read(){
        LL s=0,w=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();}
        return s*w;
    }
    inline LL ksm(LL a,LL b,LL c){
        rg LL cnt=1;
        while(b){
    		if(b&1)cnt=(1ll*cnt*a)%c;
    		a=(1ll*a*a)%c;
    		b>>=1;
        }
        return cnt;
    }
    inline void exgcd(LL a,LL b,LL &x,LL &y){
        if(!b){x=1;y=0;return;}
        exgcd(b,a%b,y,x);y-=(a/b)*x;
    }
    inline LL inv(LL a,LL b){//扩欧求逆元
        rg LL x,y;exgcd(a,b,x,y);
        return (x%b+b)%b;
    }
    inline LL CRT(LL x,LL p,LL mod){return inv(p/mod,mod)*(p/mod)*x;}
    //中国剩余定理合并
    inline LL fac(LL x,LL a,LL b){//处理阶乘的模
        if(x==0)return 1;rg LL ans=1;
        for(rg LL i=1;i<=b;i++)
        	if(i%a)ans*=i,ans%=b;
        ans=ksm(ans,x/b,b);
        for(rg LL i=1;i<=x%b;i++)
        	if(i%a)ans*=i,ans%=b;
        return (1ll*ans*fac(x/a,a,b))%b;
    }
    inline LL C(LL n,LL m,LL a,LL b){
    //求组合数模b,b即为pi^ci,a即为pi
        if(n<m)return 0;
        rg LL N=fac(n,a,b),M=fac(m,a,b),NM=fac(n-m,a,b),sum=0;
    //分别求n!,m!和(n-m)! mod b的值
        for(rg LL i=n;i;i/=a)sum+=i/a;
        for(rg LL i=m;i;i/=a)sum-=i/a;
        for(rg LL i=n-m;i;i/=a)sum-=i/a;
        return 1ll*(N*ksm(a,sum,b))%b*(inv(M,b)*inv(NM,b))%b;
    }
    inline void exlucas(LL n,LL m,LL p){
        rg LL M=p,ans=0;
        for(LL i=2;i*i<=p;i++){//对p质因数分解
    		LL tot=1;//tot即为pi^ci
    		while(M%i==0)tot*=i,M/=i;
    		ans+=CRT(C(n,m,i,tot),p,tot),ans%=p;
    //求出每个部分的值然后合并
        }
        if(M>1)ans+=CRT(C(n,m,M,M),p,M),ans%=p;
    //可能最后还剩下了一个质数未分解出来
        printf("%lld
    ",ans);
    }
    int main(){
        rg LL n=read(),m=read(),p=read();
        exlucas(n,m,p);
        return 0;
    }
    
    

    练习题---[国家集训队]礼物

  • 相关阅读:
    HDU 1850 Being a Good Boy in Spring Festival
    UESTC 1080 空心矩阵
    HDU 2491 Priest John's Busiest Day
    UVALive 6181
    ZOJ 2674 Strange Limit
    UVA 12532 Interval Product
    UESTC 1237 质因子分解
    UESTC 1014 Shot
    xe5 android listbox的 TMetropolisUIListBoxItem
    xe5 android tts(Text To Speech)
  • 原文地址:https://www.cnblogs.com/PPXppx/p/10828291.html
Copyright © 2011-2022 走看看