Address
https://www.lydsy.com/JudgeOnline/problem.php?id=4559
Solution
由容斥原理得:
這麼長的式子,一項一項地進行解析:
(1) :求「恰好完虐 個同學」時乘上容斥係數。
(2) :在 個同學中選出 個同學被完虐。
(3) :把每一科分開處理之後相乘。
(4) :在沒有被完虐的 個同學中,選出 個同學,讓他們第 課被虐。
(5) :枚舉 B 神第 科成績。
(6) :第 科被虐的同學的成績方案數。
(7) :第 科沒有被虐的同學的方案數。
顯然,我們要處理的關鍵在於 及之後的式子。
發現 不好處理。
考慮無腦展開:
注意到 是以 爲自變量的 次多項式,上拉格朗日插值法即可求得。
Code
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define For(i, a, b) for (i = a; i <= b; i++)
#define Rof(i, a, b) for (i = a; i >= b; i--)
using namespace std;
inline int read() {
int res = 0; bool bo = 0; char c;
while (((c = getchar()) < '0' || c > '9') && c != '-');
if (c == '-') bo = 1; else res = c - 48;
while ((c = getchar()) >= '0' && c <= '9')
res = (res << 3) + (res << 1) + (c - 48);
return bo ? ~res + 1 : res;
}
const int N = 111, ZZQ = 1e9 + 7;
int pwe[N][N], y[N], qaq[N], tmp[N], rps[N], inv[N], com[N][N],
C[N][N], n, m, K, U[N], R[N], ans, czk[N];
int qpow(int a, int b) {
int res = 1;
while (b) {
if (b & 1) res = 1ll * res * a % ZZQ;
a = 1ll * a * a % ZZQ;
b >>= 1;
}
return res;
}
void lagrange(int n) {
int i, j;
For (i, 1, n + 2)
y[i] = (y[i - 1] + pwe[i][n]) % ZZQ;
qaq[0] = 1;
For (i, 1, n + 2) {
tmp[0] = qaq[i] = 0;
For (j, 0, i - 1) tmp[j + 1] = qaq[j];
For (j, 0, i)
qaq[j] = (tmp[j] - 1ll * qaq[j] * i % ZZQ + ZZQ) % ZZQ;
}
For (i, 1, n + 2) {
For (j, 0, n + 2) tmp[j] = qaq[j];
Rof (j, n + 1, 0) rps[j] = tmp[j + 1],
tmp[j] = (tmp[j] + 1ll * tmp[j + 1] * i % ZZQ) % ZZQ;
int sp = 1;
For (j, 1, i - 1) sp = 1ll * sp * inv[j] % ZZQ;
For (j, 1, n - i + 2)
sp = 1ll * sp * (ZZQ - inv[j]) % ZZQ;
For (j, 0, n + 1)
com[n][j] = (com[n][j] + 1ll * y[i] *
rps[j] % ZZQ * sp % ZZQ) % ZZQ;
}
}
void init() {
int i, j; inv[1] = 1;
For (i, 2, 101) inv[i] = 1ll * (ZZQ - ZZQ / i) * inv[ZZQ % i] % ZZQ;
For (i, 0, 102) {
pwe[i][0] = 1;
For (j, 1, 100) pwe[i][j] = 1ll * pwe[i][j - 1] * i % ZZQ;
}
For (i, 0, 100) lagrange(i);
For (i, 0, 100) C[i][0] = 1;
For (i, 1, 100) For (j, 1, i)
C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % ZZQ;
}
int getval(int n, int k) {
int i, x = 1, res = 0;
For (i, 0, k + 1) res = (res + 1ll * com[k][i] * x % ZZQ) % ZZQ,
x = 1ll * x * n % ZZQ;
return res;
}
int main() {
int i, j, k, dalao;
init();
dalao = n = read(); m = read(); K = read();
For (i, 1, m) U[i] = read();
For (i, 1, m) R[i] = read();
For (i, 1, m) dalao = min(dalao, n - R[i]);
For (j, 1, m) For (k, 0, R[j] - 1) {
int miu = k & 1 ? ZZQ - 1 : 1, delta;
delta = 1ll * C[R[j] - 1][k] *
qpow(U[j], R[j] - 1 - k) % ZZQ
* getval(U[j], n + k - R[j]) % ZZQ;
czk[j] = (czk[j] + 1ll * miu * delta % ZZQ) % ZZQ;
}
For (i, K, dalao) {
int miu = i - K & 1 ? ZZQ - 1 : 1,
delta = 1ll * C[n - 1][i] * C[i][K] % ZZQ, pyz = 1;
For (j, 1, m)
pyz = 1ll * pyz * C[n - 1 - i][n - R[j] - i] % ZZQ,
pyz = 1ll * pyz * czk[j] % ZZQ;
ans = (ans + 1ll * miu * delta % ZZQ * pyz % ZZQ) % ZZQ;
}
cout << ans << endl;
return 0;
}