P5259 [JSOI2013]游戏中的学问
作者:互联网
环排列的EGF为:
\[f(x)=\sum_{3\le i} {(i-1)! x^i \over i!}=\sum_{3\le i} {x^i \over i} \]那么这道题答案就是 :
\[{n!\over k!}[x^n]f^k(x) \]数据范围太小,甚至多项式乘法不用 NTT
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int N = 3005;
int n, k, p;
inline int power(int a, int b) {
int k = b, t = 1, y = a;
while (k) {
if (k & 1) t = (1ll * t * y) % p;
y = (1ll * y * y) % p; k >>= 1;
} return t;
}
inline int inv(int x) {
return power(x, p - 2);
}
int t[N], y[N], a[N], ans = 1;
int main() {
scanf("%d%d%d", &n, &k, &p);
for (int i = k + 1; i <= n; ++i) ans = (1ll * ans * i) % p;
memset(t, 0, sizeof t); t[0] = 1;
for (int i = 3; i <= n; ++i) y[i] = inv(i);
while (k) {
if (k & 1) {
for (int i = 0; i <= n; ++i) a[i] = t[i];
memset(t, 0, sizeof t);
for (int i = 0; i <= n; ++i)
for (int j = 0; j + i <= n; ++j) {
t[i + j] += 1ll * a[i] * y[j] % p;
if (t[i + j] >= p) t[i + j] -= p;
}
} k >>= 1;
for (int i = 0; i <= n; ++i) a[i] = y[i];
memset(y, 0, sizeof y);
for (int i = 0; i <= n; ++i)
for (int j = 0; j + i <= n; ++j) {
y[i + j] += 1ll * a[i] * a[j] % p;
if (y[i + j] >= p) y[i + j] -= p;
}
} printf("%d", ((1ll * ans * t[n]) % p + p) % p);
return 0;
}
标签:JSOI2013,return,int,over,d%,1ll,P5259,include,学问 来源: https://www.cnblogs.com/wwlwakioi/p/14640471.html