T1:
求∑i=1nti∗Cn−ik−1\sum_{i=1}^nt^i*C_{n-i}^{k-1}∑i=1nti∗Cn−ik−1
1<=k<=1e7,1<=n<=1e91<=k<=1e7,1<=n<=1e91<=k<=1e7,1<=n<=1e9
也不知道怎么搞出来,总感觉这个可以列项相消:
设A=∑i=1nti∗Cn−ik−1设A=\sum_{i=1}^nt^i*C_{n-i}^{k-1}设A=∑i=1nti∗Cn−ik−1
A∗t−A=(t−1)AA*t-A=(t-1)AA∗t−A=(t−1)A
=∑i=2nti∗(Cn−(i−1)k−1−Cn−ik−1)+Cn−nk−1∗t−Cn−1k−1∗t=\sum_{i=2}^{n}t^i*(C_{n-(i-1)}^{k-1}-C_{n-i}^{k-1})+C_{n-n}^{k-1}*t-C_{n-1}^{k-1}*t=∑i=2nti∗(Cn−(i−1)k−1−Cn−ik−1)+Cn−nk−1∗t−Cn−1k−1∗t
=∑i=2nti∗Cn−ik−2+Cn−nk−1∗t−Cn−1k−1∗t=\sum_{i=2}^{n}t^i*C_{n-i}^{k-2}+C_{n-n}^{k-1}*t-C_{n-1}^{k-1}*t=∑i=2nti∗Cn−ik−2+Cn−nk−1∗t−Cn−1k−1∗t
发现这个sigmasigmasigma和A很像,不妨补一个Cn−1k−2∗tC_{n-1}^{k-2}*tCn−1k−2∗t
=∑i=1nti∗Cn−ik−2+Cn−nk−1∗t−(Cn−1k−1−Cn−1k−2)∗t=\sum_{i=1}^{n}t^i*C_{n-i}^{k-2}+C_{n-n}^{k-1}*t-(C_{n-1}^{k-1}-C_{n-1}^{k-2})*t=∑i=1nti∗Cn−ik−2+Cn−nk−1∗t−(Cn−1k−1−Cn−1k−2)∗t
=ans(n,k−1)−Cnk−1∗t=ans(n,k-1)-C_{n}^{k-1}*t=ans(n,k−1)−Cnk−1∗t
当k=1k=1k=1时,答案可以直接算,不然的话递归处理。
就发现只需要预处理Cn0..kC_n^{0..k}Cn0..k,复杂度O(k)O(k)O(k)
T2:
求第一类斯特林数的一行在ModModMod质数ppp下有多少项非0.
1<=n<=1e1000,1<=p<=1e51<=n<=1e1000,1<=p<=1e51<=n<=1e1000,1<=p<=1e5
若n比较小,容易得到暴力的分治NTT做法,根据这个来优化:
设a=n/p,b=na=n/p,b=n%pa=n/p,b=n,多项式为(∏i=1p(x+i))a∑j=1b(x+j)(\prod_{i=1}^p(x+i))^a\sum_{j=1}^b(x+j)(∏i=1p(x+i))a∑j=1b(x+j)
打表可得:
∏i=1p(x+i)≡x∗(xp−1−1)\prod_{i=1}^p(x+i)≡x*(x^{p-1}-1)∏i=1p(x+i)≡x∗(xp−1−1)
这个可以倒着证明。
那么(∏i=1p(x+i))a(\prod_{i=1}^p(x+i))^a(∏i=1p(x+i))a
=xa∗(xp−1−1)a=x^a*(x^{p-1}-1)^a=xa∗(xp−1−1)a
xax^axa没有用,丢掉。
=∑i=0aCai∗(xp−1)i∗(−1)a−i=\sum_{i=0}^{a}C_{a}^i*(x^{p-1})^i*(-1)^{a-i}=∑i=0aCai∗(xp−1)i∗(−1)a−i
对C搞事情,要非0,用库默尔或Lucas可得i在p进制下的每一位必须小于等于a的那一位。
那么i的方案就显然了。
注意到这个sigmasigmasigma所以次数非0的项至少xp−1x^{p-1}xp−1,而∑j=1b(x+j)\sum_{j=1}^b(x+j)∑j=1b(x+j)最高次项不过如此,因此答案互不干扰,乘起来即可。
T3:
用二项式展开很容易想到一个O(n3∗t2∗log k)O(n^3*t^2*log~k)O(n3∗t2∗log k)的做法。
发现枚举中间点的那个过程与二项式展开那个无关,可以分开做。
复杂度变为O((n3∗t+n2∗t2)∗log k)O((n^3*t+n^2*t^2)*log~k)O((n3∗t+n2∗t2)∗log k)
#include<cstdio>
#define pp printf
#define ll long long
#define fo(i, x, y) for(int i = x; i <= y; i ++)
#define fd(i, x, y) for(int i = x; i >= y; i --)
using namespace std;
const int mo = 998244353;
int n, k, t;
ll ksm(ll x, ll y) {
ll s = 1;
for(; y; y /= 2, x = x * x % mo)
if(y & 1) s = s * x % mo;
return s;
}
const int N = 1e7 + 5;
ll fac[N], nf[N], c[N], nt1;
int main() {
freopen("set.in", "r", stdin);
freopen("set.out", "w", stdout);
n = 1e7;
fac[0] = 1; fo(i, 1, n) fac[i] = fac[i - 1] * i % mo;
nf[n] = ksm(fac[n], mo - 2); fd(i, n, 1) nf[i - 1] = nf[i] * i % mo;
scanf("%d %d %d", &n, &k, &t);
if(t == 1) {
printf("1\n"); return 0;
}
nt1 = ksm(t - 1, mo - 2);
c[0] = 1; fo(i, 1, k) c[i] = c[i - 1] * (n - i + 1) % mo;
fo(i, 0, k) c[i] = c[i] * nf[i] % mo;
ll ans = (ksm(t, n + 1) - t + mo) * nt1 % mo;
fo(i, 2, k) ans = (ans - t * c[i - 1] % mo + mo) * nt1 % mo;
pp("%lld", ans * ksm(c[k], mo - 2) % mo);
}
#pragma GCC optimize(2)
#include<cmath>
#include<vector>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define pp printf
#define ll long long
#define ld long double
#define fo(i, x, y) for(int i = x, B = y; i <= B; i ++)
#define ff(i, x, y) for(int i = x, B = y; i < B; i ++)
#define fd(i, x, y) for(int i = x, B = y; i >= B; i --)
#define pb push_back
using namespace std;
const int N = 1e5 + 5;
const int M = 1 << 17;
struct P {
ld x, y;
P(ld _x = 0, ld _y = 0) {x = _x, y = _y;}
};
P operator-(P a, P b) { return P(a.x - b.x, a.y - b.y);}
P operator+(P a, P b) { return P(a.x + b.x, a.y + b.y);}
P operator*(P a, P b) { return P(a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x);}
const ld pi = acos(-1);
int r[M];
P a[M], b[M], w[M];
void dft(P *a, int tp, int F) {
int n = 1 << tp;
ff(i, 0, n) if(r[i] < i) swap(a[r[i]], a[i]);
for(int h = 1; h < n; h *= 2) {
int b = n / h / 2;
for(int j = 0; j < n; j += 2 * h) {
P A, *l = a + j, *r = a + j + h, *W = w;
ff(i, 0, h) {
A = *r * *W, *r = *l - A, *l = *l + A;
l ++, r ++, W += b;
}
}
}
}
void fft(P *a, P *b, int tp) {
int n = 1 << tp;
ff(i, 0, n) r[i] = r[i / 2] / 2 + (i & 1) * n / 2;
ff(i, 0, n) w[i] = P(cos(2 * pi * i / n), sin(2 * pi * i / n));
dft(a, tp, 1); dft(b, tp, 1);
ff(i, 0, n) a[i] = a[i] * b[i];
fo(i, 1, n / 2) swap(w[i], w[n - i]);
dft(a, tp, -1); ff(i, 0, n) a[i].x /= n;
}
int n, Mo;
typedef vector<int> V;
V operator * (V p, V q) {
int n = p.size() + q.size();
int tp = 0; while(1 << ++ tp < n);
ff(i, 0, 1 << tp) a[i] = b[i] = P(0, 0);
ff(i, 0, p.size()) a[i].x = p[i];
ff(i, 0, q.size()) b[i].x = q[i];
fft(a, b, tp);
p.clear(); ff(i, 0, n - 1) p.pb((ll) round(a[i].x) % Mo);
return p;
}
V p[N];
void dg(int x, int y) {
if(x >= y) return;
int m = x + y >> 1;
dg(x, m); dg(m + 1, y);
p[x] = p[x] * p[m + 1];
}
char str[1005];
int lt, t[1005], bl[1005];
int yu;
const int mo = 998244353;
void chu() {
yu = 0;
fd(i, lt, 1) {
t[i] += yu * 10000;
yu = t[i] % Mo;
t[i] /= Mo;
}
while(lt > 1 && !t[lt]) lt --;
}
int main() {
freopen("math.in", "r", stdin);
freopen("math.out", "w", stdout);
{
scanf("%s", str + 1); lt = strlen(str + 1);
int s = 0; fd(i, lt, 1) bl[i] = bl[i + 1] + !s, s = (s + 1) % 4;
fo(i, 1, lt) t[bl[i]] = t[bl[i]] * 10 + str[i] - '0';
}
scanf("%d", &Mo);
chu();
if(yu == Mo - 1) {
yu = 0;
t[1] ++;
fo(i, 1, lt) {
t[i + 1] += t[i] / 10000;
t[i] %= 10000;
}
while(t[lt + 1]) lt ++;
}
fo(i, 1, yu) p[i].pb(1), p[i].pb(i % Mo);
dg(1, yu);
ll ans = 0;
ff(i, 0, p[1].size()) ans += p[1][i] != 0;
if(!yu) ans = 1;
while(!(lt == 1 && !t[1])) {
chu();
ans = ans * (yu + 1) % mo;
}
pp("%lld\n", ans);
}
#pragma GCC optimize(2)
#include<cstdio>
#include<cstring>
#define pp printf
#define ll long long
#define fo(i, x, y) for(int i = x; i <= y; i ++)
using namespace std;
const int mo = 998244353;
const int N = 51;
int n, k, q, t, x, y;
int a[N][N], o;
ll f[2][N][N], ans[N][N];
ll c[N][N], g[N][N], p[N][N];
struct nod {
ll s[N][N][N];
} s0, s1, s2, s3;
void plus(nod &a, nod &b) {
fo(i, 1, n) fo(j, 1, n) fo(u, 0, t)
a.s[i][j][u] += b.s[i][j][u],
a.s[i][j][u] > mo ? a.s[i][j][u] -= mo : 0;
}
ll ds;
nod b, d;
void ch(nod &a) {
memset(d.s, 0, sizeof d.s);
fo(i, 1, n) fo(j, 1, n) fo(v, 0, t) {
fo(z, 1, n) {
d.s[i][j][v] += a.s[i][z][v] * g[z][j];
if(!(z & 7)) d.s[i][j][v] %= mo;
}
d.s[i][j][v] %= mo;
}
fo(i, 1, n) fo(j, 1, n) fo(u, 0, t) d.s[i][j][u] %= mo;
memset(a.s, 0, sizeof a.s);
ll s = 1;
fo(u, 0, t) {
fo(v, 0, t - u) {
ll ss = s * c[u + v][u] % mo;
fo(i, 1, n) fo(j, 1, n) a.s[i][j][u + v] += d.s[i][j][v] * ss % mo;
}
s = s * ds % mo;
}
fo(i, 1, n) fo(j, 1, n) fo(u, 0, t) a.s[i][j][u] %= mo;
}
int main() {
freopen("road.in", "r", stdin);
freopen("road.out", "w", stdout);
scanf("%d %d %d %d", &n, &k, &q, &t);
fo(i, 1, n) fo(j, 1, n) scanf("%d", &a[i][j]);
if(k == 0) {
pp("0\n"); return 0;
}
k --;
fo(i, 0, t) {
c[i][0] = 1;
fo(j, 1, i) c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % mo;
}
fo(i, 1, n) fo(j, 1, n) g[i][j] = a[i][j];
ds = 1; fo(i, 1, n) s1.s[i][i][0] = 1;
for(; k; k /= 2) {
if(k & 1) {
s3 = s0; ch(s3);
plus(s3, s1);
plus(s3, s2);
plus(s0, s3);
ch(s1);
ch(s2);
} else {
s3 = s0;
plus(s3, s1); plus(s3, s2);
ch(s3);
plus(s2, s3);
}
fo(i, 1, n) fo(j, 1, n) p[i][j] = g[i][j], g[i][j] = 0;
fo(i, 1, n) fo(j, 1, n) fo(u, 1, n) g[i][j] += p[i][u] * p[u][j] % mo;
fo(i, 1, n) fo(j, 1, n) g[i][j] %= mo;
ds *= 2;
}
plus(s0, s1);
fo(ii, 1, q) {
scanf("%d %d", &x, &y);
pp("%lld\n", s0.s[x][y][t]);
}
}