bzoj1951 [SDOI2010]古代猪文

题目链接

solution

理解完题意。发现就是求\(g^{\sum\limits_{k|n}C_n^k}\)

利用欧拉降幂,可以将式子写成\(g^{\sum\limits_{k|n}C_n^k\%\phi(mod)}\)

只要想办法把指数求出来就行了。

看一下数据范围,发现\(n\)比较大,不能直接计算组合数。然后考虑用\(lucas\)。但是模数也比较大。

因为模数不是质数,对其进行质因数分解得到\(2,3,4679,35671\)。发现这四个质数都是可以进行\(lucas\)的。所以思路就很明显了,先将模数分解质因子,然后分别求出答案。得到四个形如\(\sum\limits_{k|n}C_n^k\equiv a_i(mod\ m_i)\)的式子。然后用\(CRT\)将其合并起来,得到\(\sum\limits_{k|n}C_n^k\%\phi(mod)\)

PS:因为欧拉降幂必须满足底数与模数互质,因为题目所给模数为质数,所以当\(g\)为所给模数倍数时不能使用欧拉降幂,而此时答案显然为\(0\),需要特判。

code

/*
* @Author: wxyww
* @Date:   2020-04-22 09:31:36
* @Last Modified time: 2020-04-22 09:52:12
*/
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<ctime>
using namespace std;
typedef long long ll;
const int N = 100010;
ll read() {
	ll x = 0,f = 1;char c = getchar();
	while(c < '0' || c > '9') {
		if(c == '-') f = -1; c = getchar();
	}
	while(c >= '0' && c <= '9') {
		x = x * 10 + c - '0'; c = getchar();
	}
	return x * f;
}

ll qm(ll x,ll y,ll mod) {
	ll ret = 1;
	for(;y;y >>= 1,x = x * x % mod)
		if(y & 1) ret = ret * x % mod;
	return ret;
}
int jc[N],inv[N];

ll C(int n,int m,int mod) {
	if(n < m) return 0;
	if(n < mod) return jc[n] * inv[m] % mod * inv[n - m] % mod;
	return C(n % mod,m % mod,mod) * C(n / mod,m / mod,mod) % mod;
}
ll a[5];
ll b[5] = {0,2,3,4679,35617};
ll solve(int n,int mod) {
	jc[0] = 1;
	for(int i = 1;i < mod;++i) jc[i] = jc[i - 1] * i % mod;
	inv[mod - 1] = qm(jc[mod - 1],mod - 2,mod);

	// cout<<inv[mod - 1]<<endl;

	for(int i = mod - 2;i >= 0;--i) inv[i] = inv[i + 1] * (i + 1) % mod;

	ll ret = 0;

	for(int i = 1;i * i <= n;++i) {
		if(n % i) continue;
		ret += C(n,i,mod);
		ret %= mod;
		if(i * i != n) ret += C(n,n / i,mod),ret %= mod;
		// if(mod == 2) {
			// printf("!!%d\n",C(n,i,mod));
		// }
	}

	return ret;
}
int main() {
	int n = read(),G = read();
	if(G % 999911659 == 0) {
		puts("0");return 0;
	}
	for(int i = 1;i <= 4;++i) {
		a[i] = solve(n,b[i]);
		// printf("%d\n",a[i]);
	}
	ll M = 999911658;
	ll ans = 0;
	for(int i = 1;i <= 4;++i) {
		ans += a[i] * (M / b[i]) % M * qm(M / b[i],b[i] - 2,b[i]) % M;
		ans %= M;
	}
	cout<<qm(G,ans,M + 1);
	return 0;
}
posted @ 2020-04-22 10:10  wxyww  阅读(198)  评论(0编辑  收藏  举报