输入4824452825608873 735137 688586(有文件读写)
代码中注释部分会出bug,运行代码得知,当 prod 变量为0时,pd=-233345,i+n=1961286755,pk=1123280.
而prod=pd*(i+n)%pk,经计算器检验正确的prod=-503635显然不为0,单独写代码计算-233345*1961286755LL%1123280也不为0,但是计算pd*(i+n)%pk时结果总是0。
显然因为n是longlong,所以算式计算时会自动强转成longlong,应该不存在溢出的问题(
#include<bits/stdc++.h>
using namespace std;
#define reg register
#define ll long long
extern "C" {
namespace io {
#define BUFS 100000
static char in[BUFS], *p = in, *pp = in;
#define gc (p == pp && (pp = (p = in) + fread(in, 1, BUFS, stdin), p == pp) ? EOF : *p++)
inline ll read() {
reg ll x = 0; reg char ch, f = 0;
while (!isdigit(ch = gc)) f |= ch == '-';
while (isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48), ch = gc;
return f ? -x : x;
}
}
}
#define rd io :: read
ll m, n;
int p, fac[1001], pw[1001], e, A[1001], B[1001];
inline int qpow(int a, ll b, int mod) {
reg int res = 1;
for (; b; b >>= 1, a = (ll)a * a % mod) (b & 1) && (res = (ll)res * a % mod);
return res;
}
int exgcd(int&x, int&y, int a, int b) {
if (b == 0) {
x = 1, y = 0;
return a;
}
int g = exgcd(x, y, b, a % b), t = x;
x = y, y = t - a / b * y;
return g;
}
inline int inv(int a, int mod) {
int x, y;
exgcd(x, y, a, mod);
return x;
}
inline int calc(ll n, int p, int pk) {
if (!n) return 1;
reg int rho = pk, prod = 1;
for (reg int i = 1; i <= pk; ++i)
if (i % p) prod = (ll)prod * i % pk;
prod = qpow(prod, n / pk, pk);
for (reg int i = pk * (n / pk) + 1 - n, pd; i <= 0; ++i)
if ((i+n) % p) pd=prod,prod = pd * (i + n) % pk, prod || (printf("%d %d %d", pd, i+n,pk), fclose(stdin), freopen("con", "r", stdin), getchar(),0);//就是这里
return (ll)calc(n / p, p, pk) * prod % pk;
}
inline ll g(ll n, int p) {
if (n < p) return 0;
return n / p + g(n / p, p);
}
inline int cal(ll n, ll m, int p, int pk) {
int f1 = calc(n, p, pk), f2 = inv(calc(m, p, pk), pk), f3 = inv(calc(n - m, p, pk), pk);
int G = qpow(p, g(n, p) - g(m, p) - g(n - m, p), pk);
return (ll)f1 * f2 % pk * f3 % pk * G % pk;
}
int main() {
freopen("2.in", "r", stdin);
n = rd(), m = rd(), p = rd();
reg int tmp = p;
for (reg int i = 2, j = sqrt(p), d = 0; i <= j; ++i) {
if (!tmp) break;
if (tmp % i == 0) {
fac[++e] = i;
d = 1;
do
tmp /= i, d *= i;
while (tmp % i == 0);
pw[e] = d;
}
}
if (tmp > 1) ++e, fac[e] = pw[e] = tmp;
for (reg int i = 1, P, PK; i <= e; ++i)
P = fac[i], PK = pw[i],
A[i] = cal(n, m, P, PK),
B[i] = PK;
reg int ans = 0;
for (reg int i = 1, M, T; i <= e; ++i)
M = p / B[i], T = inv(M, B[i]),
ans = (ans + (ll) A[i] * M % p * T % p + p) % p;
printf("%d", ans);
return 0;
}