扩展Lucas板子

实在看不惯自己以前的代码风格,改了一下。。。

#include <cstdio>
#include <iostream>
using namespace std;
inline int add(int a,int b,int p)
{a+=b;return a>=p?a-p:a;}
inline int ch(int a,int b,int p)
{return 1LL*a*b%p;}
inline int ksm(int a,int b,int p)
{
    int ans=1;
    while(b)
    {
        if(b&1)ans=ch(ans,a,p);
        a=ch(a,a,p),b>>=1;
    }
    return ans;
}
int MOD;
int fAC(int n,int p,int ct)
{
    if(!n)return 1;
    int res=n%ct,t=1;
    for(int i=2;i<ct;i++)
        if(i%p>0)t=ch(t,i,ct);
    t=ksm(t,n/ct,ct);
    for(int i=2;i<=res;i++)
        if(i%p>0)t=ch(t,i,ct);
    return ch(fAC(n/p,p,ct),t,ct);
}
int C(int n,int m,int p,int ct)
{
    if(n<m)return 0;
    int tx=fAC(n,p,ct),ty=fAC(m,p,ct),tz=fAC(n-m,p,ct),co=0;
    for(int i=n;i;i/=p)co+=i/p;
    for(int i=m;i;i/=p)co-=i/p;
    for(int i=n-m;i;i/=p)co-=i/p;
    int phi=ct-ct/p;
    return ch(ch(tx,ch(ksm(ty,phi-1,ct),ksm(tz,phi-1,ct),ct),ct),ksm(p,co,ct),ct);
}
int luc(int n,int m,int MOD)
{
    int x=MOD,ans=0;
    for(int i=2;i*i<=x;i++)
        if(x%i==0)
        {
            int cnt=1;
            while(x%i==0)x/=i,cnt*=i;
            int get=C(n,m,i,cnt),m=MOD/cnt;
            ans=add(ans,ch(ch(m,ksm(m,cnt-cnt/i-1,cnt),MOD),get,MOD),MOD);
        }
    if(x>1)
    {
        int cnt=x,i=x;
        int get=C(n,m,i,cnt),m=MOD/cnt;
        ans=add(ans,ch(ch(m,ksm(m,cnt-cnt/i-1,cnt),MOD),get,MOD),MOD);
    }
    return ans;
}
int main()
{
    int n,m,p;
    cin>>n>>m>>p;
    cout<<luc(n,m,p);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/includelhc/article/details/82532233