题目链接:
https://www.luogu.com.cn/problem/P4720
与卢卡斯定理的区别:
在求解 的问题上,lucas方法中p必须为质数,Exlucas方法中p不一定是质数,也可以是合数。
Exlucas作用:
求解 p为非质数的 问题
方法中会使用快速幂,中国剩余定理等。
ac代码:
#include<bits/stdc++.h>using namespace std;#define int long longconst int N = 1e5+5;int a[N],b[N];int qmi(int a,int b,int p){int ans = 1;while(b){if(b&1)ans = ans*a%p;b >>= 1;a = a*a%p;}return ans;}int exgcd(int a,int b,int &x,int &y){if(!b){x=1,y=0;return a;}int d = exgcd(b,a%b,y,x);y -= a/b*x;return d;}int inv(int a,int p){int x,y;int d = exgcd(a,p,x,y);return (x%p+p)%p;}int china(int n,int p){int ans = 0;for (int i=1;i<=n;i++){int mi = p/a[i];int x = inv(mi,a[i]);ans = (ans+b[i]*mi%p*x%p)%p;}return ans;}int g(int n,int p){if(n<p)return 0;return g(n/p,p)+n/p;}int f(int n,int p,int pk){if(!n)return 1;int rou = 1;int rem = 1;for (int i=1;i<=pk;i++)if(i%p)rou = rou*i%pk;rou = qmi(rou,n/pk,pk);for (int i=pk*(n/pk);i<=n;i++)if(i%p)rem = rem*(i%pk)%pk;return f(n/p,p,pk)*rou%pk*rem%pk;}int c_pk(int n,int m,int p,int pk){int fn = f(n,p,pk),fm = inv(f(m,p,pk),pk),fnm = inv(f(n-m,p,pk),pk);int mi = qmi(p,g(n,p)-g(m,p)-g(n-m,p),pk);return fn*fm%pk*fnm%pk*mi%pk;}int exlucas(int n,int m,int p){int tmp = p,cnt = 0;for (int i=2;i<=tmp/i;i++)if(tmp%i==0){int pk = 1;while(tmp%i==0)tmp/=i,pk*=i;a[++cnt] = pk;b[cnt] = c_pk(n,m,i,pk);}if(tmp>1){a[++cnt] = tmp;b[cnt] = c_pk(n,m,tmp,tmp);}return china(cnt,p);}signed main (){int n,m,p;cin>>n>>m>>p;cout<<exlucas(n,m,p);return 0;}
