拓展lucas [HZOI 2016]艾米利亚的魔法
这道题真令人发懵。。
首先要考虑如何降幂,利用这个式子
但我们发现φ(p)=27092310,是一个合数,所以在使用lucas定理时要把模数分解质因数,用中国剩余定理处理一下。
这题出的挺综合的。。。
#pragma GCC optimize("O3")
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 200005
#define mod 54184622
#define M 27092310
#define ll long long
using namespace std;
int read()
{
int sum=0,f=1;char x=getchar();
while(x<'0'||x>'9'){if(x=='-')f=-1;x=getchar();}
while(x>='0'&&x<='9'){sum=(sum<<1)+(sum<<3)+x-'0';x=getchar();}
return sum*f;
}
ll n,g,a[6],b[6],pri[6]={2,3,5,7,129011},ans;
ll s1[6][1000005],s2[6][1000005];
ll gcd(ll x,ll y){return !y?x:gcd(y,x%y);}
ll cheng(ll x,ll n,ll p)
{
ll ans=1;
while(n)
{
if(n&1)ans=ans*x%p;
x=x*x%p;
n/=2;
}
return ans;
}
ll get(ll n,ll m,ll p,int i)
{
if(m>n)return 0;
return ((s1[i][n]*s2[i][m]%p)*s2[i][n-m])%p;
}
ll lucas(ll n,ll m,ll p,int i)
{
if(m==0)return 1;
return get(n%p,m%p,p,i)*lucas(n/p,m/p,p,i)%p;
}
ll C(ll n,ll m)
{
if(m>n)return 0;
ll sum=0;
for(int i=0;i<5;i++)
{
ll k=lucas(n,m,pri[i],i);
sum=(sum+k*a[i]*b[i]%M)%M;
}
return sum;
}
void init()
{
for(int i=0;i<5;i++)
{
s1[i][0]=1;
for(ll j=1;j<=1000000;j++)s1[i][j]=(s1[i][j-1]*j)%pri[i];
for(ll j=0;j<=1000000;j++)s2[i][j]=cheng(s1[i][j],pri[i]-2,pri[i]);
a[i]=M/pri[i];
b[i]=cheng(a[i],pri[i]-2,pri[i]);
}
}
int main()
{
//freopen("aimiliyademagic.in","r",stdin);
//freopen("aimiliyademagic.out","w",stdout);
n=read();g=read();
init();
for(ll i=1;i<=n;i++)
{
ll k=gcd(i,n);
if(k!=1)continue;
ans+=C(g,i);
ans%=M;
}
printf("%lld\n",cheng(n,ans+M,mod));
}