有一个 n × n ( n ≤ 1 0 6 ) n \times n ( n \leq 10^6 ) n×n(n≤106)的正方形网格,用红色,绿色,蓝色三种颜色染色,求有多少种染色方案使得至少一行或一列是同一种颜色。结果对 998244353 998244353 998244353 取模。
sol:
可以二维容斥,得到
∑ i = 0 n ∑ j = 0 n C n i C n j ( − 1 ) i + j ( ( ! i ∣ ∣ ! j ) ? 3 i + j : 3 ) 3 ( n − j ) ( n − i ) \sum_{i=0}^n\sum_{j=0}^n{C_n^iC_n^j(-1)^{i+j}((!i||!j)?3^{i+j}:3)3^{(n-j)(n-i)}} i=0∑nj=0∑nCniCnj(−1)i+j((!i∣∣!j)?3i+j:3)3(n−j)(n−i)
发现后边的指数 3 ( n − i ) ( n − j ) 3^{(n-i)(n-j)} 3(n−i)(n−j)可以变成 ( 3 n − i ) n − j (3^{n-i})^{n-j} (3n−i)n−j然后二项式定理
复杂度 n l o g n nlogn nlogn。
#include
#include
typedef long long LL;
const LL p = 998244353;
const int N = 1e6+7;
inline LL FST(LL b, LL k) {
LL ans = 1;b %= p;
while (k) {
if (k & 1) ans = ans * b % p; b = b * b % p; k >>= 1;
} return ans;
}
LL ifac[N], fac[N], inv[N];
const int lim = 1e6;
void init() {
inv[0] = inv[1] = fac[1] = fac[0] = 1;
for (int i = 2; i <= lim; i++)
inv[i] = (p - p / i) * inv[p % i] % p;
for (int i = 2; i <= lim; i++)
fac[i] = (fac[i - 1] * i) % p,
inv[i] = inv[i - 1] * inv[i] % p;
}
inline LL C(LL a, LL b) {
return (fac[a] * inv[a - b]) % p * inv[b] % p;
}
LL n, m;
int main() {
init();scanf("%lld", &n);LL ans = FST(3, n * n); LL ret = 0;
for (int i = 1; i <= n; i++) {
LL res = C(n, i) * FST(-1, i) % p * (FST(FST(3, n - i) - 1, n) % p - FST(3, (n * (n - i)))) % p * 3LL % p;
ret = ((ret + res) % p + p) % p;
}
for (int i = 0; i <= n; i++) {
LL res = C(n, i) * FST(-1, i) % p * FST(3, n * (LL)(n - i) + i) % p * 2LL % p;
ret = ((ret + res) % p + p) % p;
} ret = ((ret - FST(3, n * n)) % p + p) % p;
ans = ((ans - ret) % p + p) % p;
printf ("%lld", (ans % p + p) % p);
}