luogu2480 [SDOI2010]古代猪文
题意一开始没TM读懂。。。
就是给定一个\(G\le10^{10},N\le10^9\),求\(G^{\sum_{d|n}{n\choose d}}\),对999911659取模
由于999911659是质数,所以上面的数可以对999911658取模
现在问题转化为求\(\sum_{d|n}{n\choose d}\)对999911658取模(然后加个快速幂就行了)
对999911658质因数分解,可得\(999911658=2*3*4679*35617\)
由于次数都是一次,所以对这些数进行卢卡斯定理,然后中国剩余定理合并即可
不错的一道题,综合了好几道数论题一起考
#include <cstdio>
#define int long long
using namespace std;
int g, n, d[2333], tot;
int p, fac[40010], inv[40010];
int exgcd(int a, int b, int x, int y)
{
if (b == 0) { x = 1, y = 0; return x; }
long long res = exgcd(b, a % b, y, x);
y -= a / b * x; return res;
}
struct fuck
{
int x, y;
fuck(int x = 0, int y = 0) : x(x), y(y) {}
};
int qpow(int x, int y)
{
int res = 1;
for (x %= p; y > 0; x = x * x % p, y >>= 1) if (y & 1) res = res * x % p;
return res;
}
int c(int n, int m)
{
if (n < m || m < 0) return 0;
if (n < p && m < p) return fac[n] * inv[m] % p * inv[n - m] % p;
return c(n / p, m / p) * c(n % p, m % p) % p;
}
int work()
{
int ans = 0;
fac[0] = 1;
for (int i = 1; i < p; i++) fac[i] = fac[i - 1] * i % p;
inv[p - 1] = qpow(fac[p - 1], p - 2);
for (int i = p - 1; i >= 1; i--) inv[i - 1] = inv[i] * i % p;
for (int i = 1; i <= tot; i++)
ans = (ans + c(n, d[i])) % p;
return ans;
}
signed main()
{
scanf("%lld%lld", &n, &g);
if (g % 999911659 == 0)
{
printf("0\n");
return 0;
}
for (int i = 1; i * i <= n; i++)
if (n % i == 0)
{
d[++tot] = i;
if (i * i != n) d[++tot] = n / i;
}
long long ans1, ans2, ans3, ans4;
p = 2, ans1 = work();
p = 3, ans2 = work();
p = 4679, ans3 = work();
p = 35617, ans4 = work();
p = 999911659;
printf("%lld\n", qpow(g, (499955829 * ans1 + 333303886 * ans2 + 289138806 * ans3 + 877424796 * ans4) % (p - 1)));
return 0;
}
一开始全WA了一发,#define int long long后95pts,第13个点read1expect 0
后来观察讨论发现是需要判断g和999911659不互质并且指数和p-1不互质的情况了(就是g是999911659倍数情况)
或者就是说\((kp)^{z(p-1)}\)被模成了0^0,然后快速幂返回了1