[SDOI2010]古代猪文

考虑题目要求求:
\(g^{\sum\limits_{i | n}\binom{n}{i}}\pmod {999911659}\)

那么因为 \(999911659\) 为质数,\((a,p) = 1\),所以依据欧拉定理有
\(g^x = g^{x\bmod p - 1} \pmod p\)
所以我们转而求
\(\sum\limits_{i | n}\binom{n}{i}\bmod 999911658\)
因为\(999911658\)不是质数,所以我们拆成\(\prod p^x\)
然后扩展Lucas。
出题人比较有良心
\(999911658 = 2 * 3 * 4670 * 35617\)

所以只要\(Lucas\)就行了。

特判\(g = 0\)
因为指数可能变成 \(0\) 了。

#include<iostream>
#include<cstdio>
#define ll long long 
#define N 35617

ll A[5],B[5];

ll s[N],inv[N];

inline ll pow(ll a,ll b,ll p){
	ll ans = 1;
	while(b){
		if(b & 1)ans = ans * a % p;
		a = a * a % p;
		b >>= 1;
	}
	return ans;
}

inline ll C(ll n,ll m,ll p){
	if(n < m) return 0;
	return s[n] * inv[m] % p * inv[n - m] % p;
}

inline ll Lucas(ll n,ll m,ll p){
	if(n < m)return 0;
	if(n == 0)return 1;
	return Lucas(n / p,m / p,p) * C(n % p,m % p,p) % p; 
}

inline void solve(ll n,ll k){
	ll p = A[k];
	s[0] = 1;
	for(int i = 1;i <= p - 1;++i)
	s[i] = i * s[i - 1] % p; 
	inv[p - 1] = pow(s[p - 1],p - 2,p);
	for(int i = p - 2;i >= 0;--i)
	inv[i] = (i + 1) * inv[i + 1] % p;
	ll ans = 0;
	for(int i = 1;i * i <= n;++i){
		if(n % i == 0){
		ans = (ans + Lucas(n,i,p)) % p;
		if((n / i) != i)	
		ans = (ans + Lucas(n,n / i,p)) % p;
		}
	}
	B[k] = ans;
}

int main(){
	A[1] = 2;
	A[2] = 3;
	A[3] = 4679;
	A[4] = 35617;
	ll n,g;
	scanf("%lld%lld",&n,&g);
	for(int i = 1;i <= 4;++i){
		solve(n,i);
	}
	ll M = 999911658,m;
	ll ans = 0;
	for(int i = 1;i <= 4;++i){
		m = M / A[i];
		ll t = pow(m,A[i] - 2,A[i]);
		ans = (ans + t * B[i] % M * m % M) % M;
	}
	if(g % (999911659) == 0)
	std::cout<<0<<std::endl;
	else
	std::cout<<pow(g,ans,999911659)<<std::endl;
}
posted @ 2021-09-09 21:14  fhq_treap  阅读(129)  评论(0编辑  收藏  举报