【洛谷P2480】古代猪文

题目大意:求

\[G^{\sum\limits_{d|N}\binom{n}{k}} mod\ \ 999911659 \]

题解:卢卡斯定理+中国剩余定理

利用卢卡斯定理求出指数和式对各个素模数的解,再利用中国剩余定理合并四个解即可。

也可以在枚举 N 的因子的过程中,对于计算的四个解直接进行中国剩余定理的合并,答案不变。

代码如下

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;

const LL mod = 999911658;
const LL md[] = {2, 3, 4679, 35617};
const int maxn = 40000;
LL fac[maxn];

inline LL fpow(LL a, LL b, LL c) {
	LL ret = 1 % c;
	for (; b; b >>= 1, a = a * a % c) {
		if (b & 1) {
			ret = ret * a % c;
		}
	}
	return ret;
}
inline LL comb(LL x, LL y, LL p) {
	if (y > x) {
		return 0;
	}
	return fac[x] * fpow(fac[x - y], p - 2, p) % p * fpow(fac[y], p - 2, p) % p;
}
LL Lucas(LL x, LL y, LL p) {
	if (y == 0) {
		return 1;
	}
	return Lucas(x / p, y / p, p) * comb(x % p, y % p, p) % p;
}
LL CRT(vector<LL> &v) {
	LL ret = 0;
	for (int i = 0; i < 4; i++) {
		ret = (ret + mod / md[i] * fpow(mod / md[i], md[i] - 2, md[i]) % mod * v[i] % mod) % mod;
	}
	return ret;
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);
	LL n, G;
	cin >> n >> G;
	if (G % (mod + 1) == 0) {
		cout << 0 << endl;
		return 0;
	}
	vector<LL> v;
	for (int i = 0; i < 4; i++) {
		LL res = 0;
		fac[0] = 1;
		for (int j = 1; j < 35617; j++) {
			fac[j] = fac[j - 1] * j % md[i];
		}
		for (int j = 1; j <= sqrt(n); j++) {
			if (n % j == 0) {
				res = (res + Lucas(n, n / j, md[i])) % md[i];
				if (j * j != n) {
					res = (res + Lucas(n, j, md[i])) % md[i];
				}
			}
		}
		v.push_back(res);
	}
	LL p = CRT(v);
	cout << fpow(G, p, mod + 1) << endl;
	return 0;
}
/*
2
3
4679
35617
*/
posted @ 2019-10-10 13:12  shellpicker  阅读(188)  评论(0编辑  收藏  举报