題意:給你 a,n,m, 求a^( C(n,m) ) )% mod,mod = 999911659。
題解:組合數取模再加上題目的數據範圍是肯定要用lucas定理的,但是根據 歐拉定理可知ans = a^( C(n, m) %(mod-1) + mod-1 ) %mod,因爲這裏mod是一個質數,所以mod-1就不是一個質數,而lucas要求取模的模數一定是質數,所以不好直接用lucas定理。那麼我們可以把mod-1分解質因數(mod-1拆成素數相乘爲2*3*4679*35617,可以直接打表給出),然後用lucas定理分別求C(n, m)) % m, m = 2, 3, 4679, 35617,因爲模都是互質的數,所以用中國剩餘定理合併它們然後快速冪求解最後的答案即可。
需要注意: 歐拉定理的使用條件是gcd(a,mod)==1,如果a==mod則要輸出0。
附上代碼:
#include<iostream>
#include<algorithm>
#include<string.h>
#include<stdlib.h>
#include<stdio.h>
#include<math.h>
#include<queue>
const int mod=999911659;
const int inf=2147483640;
typedef long long LL;
using namespace std;
int t[4]= {2,3,4679,35617};
int n,m,aa,r[4],fac[4][100010];
int power(LL a,int b,LL c)//快速冪
{
a%=c;
LL res=1;
while (b)
{
if (b&1) res=res*a%c;
b>>=1;
a=a*a%c;
}
return res;
}
int C(int n,int m,int p) //組合數
{
if (m<n) return 0;
return (LL)(fac[p][m]*power((LL)fac[p][n]*fac[p][m-n],t[p]-2,t[p]))%t[p];
}
int Lucas(int n,int m,int p) //盧卡斯定理
{
if (m==0) return 1;
return C(n%t[p],m%t[p],p)*Lucas(n/t[p],m/t[p],p)%t[p];
}
void exgcd(int a,int b,LL &x,LL &y)//擴展歐幾里得
{
if (b==0)
{
x=1,y=0;
return;
}
exgcd(b,a%b,y,x);
y-=a/b*x;
}
int CRT()//中國剩餘定理
{
LL x,y,M=t[0],R=r[0];
for (int i=1; i<4; i++)
{
int mm=t[i],rr=r[i];
exgcd(M,mm,x,y);
x=((rr-R)*x%mm+mm)%mm;
R+=M*x;
M*=mm;
}
return R;
}
int main()
{
while(scanf("%d%d%d",&aa,&n,&m)!=EOF){
memset(fac,0,sizeof(fac));
memset(r,0,sizeof(r));
if (aa==mod)
{
printf("0\n");
return 0;
}
for (int i=0; i<4; i++)
{
fac[i][0]=1;
for (int j=1; j<=t[i]; j++)
fac[i][j]=fac[i][j-1]*j%t[i];
}
for (int i=0; i<4; i++)
{
r[i]=(r[i]+Lucas(m,n,i))%t[i];
}
printf("%d\n",power(aa,CRT(),mod));
}
return 0;
}