CodeForces - 997C Sky Full of Stars

On one of the planets of Solar system, in Atmosphere University, many students are fans of bingo game.
It is well known that one month on this planet consists of $n^2$days, so calendars, represented as square matrix
$n$ by n are extremely popular.
Weather conditions are even more unusual. Due to the unique composition of the atmosphere, when interacting with sunlight, every day sky takes one of three colors: blue, green or red.
To play the bingo, you need to observe the sky for one month — after each day, its cell is painted with the color of the sky in that day, that is, blue, green or red.
At the end of the month, students examine the calendar. If at least one row or column contains only cells of one color, that month is called lucky.
Let’s call two colorings of calendar different, if at least one cell has different colors in them. It is easy to see that there are
$3^{n * n}$different colorings. How much of them are lucky? Since this number can be quite large, print it modulo $998244353$.

题目链接

CodeForces - 997C Sky Full of Stars

题解

有空补一下套题题解Qwq,然而我只是pilpuQwq
设 $f(i,j)$ 表示至少有i行j列一种颜色的方案数
可以发现,当ij有相交时颜色只能为一种

那么对于$i=0 || j=0$ 时 $f(i,j) = C_n^i C_n^j3^{(n - i) *(n - j) + i + j}$

否则$f(i,j) = C_n^i C_n^j3^{(n - i) * (n - j) + 1}$
可以得到一种很显然的容斥方法
对于第一种情况单独算,复杂度$nlogn$
对于第二个式子,容斥是$n^2$的,推式子

$3\sum_{i=1}^{n}\sum_{j=1}^{n}{C_n^iC_n^j(-1)^{i+j+1}3^{(n-i)(n-j)}}$
设 $T=3^{ij}$ 换元 $3^{(n - i)*(n - j)}$

原式 $=3\sum_{i = 0}^{n - 1}\sum_{j = 0}^{n - 1}C_n^iC_n^j(-1)^{i + j - 1}3^{ij}$
拆 $(-1)^{i + j + 1}$
$=3\sum_{i = 0}^{n - 1}C_n^i(-1)^{i + 1}\sum_{j = 0}^{n - 1}C_n^j(-3^i)^{j}$
另 $T=(-3)^i$
对于后面那部分二项式定理因式分解

$=3\sum_{i = 0}^{n - 1} C_n^i (-1)^{i + 1} *[(1 + T)^n - T^n]$
复杂变成了$nlogn$

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 1000007;
const int mod = 998244353;
int n,fac[maxn],inv[maxn];
int fstpow(int x,int y) {
x %= mod;
int ret = 1;
for(; y; y >>= 1,x = 1ll * x * x % mod)
if(y & 1) ret = 1ll * ret * x % mod;
return ret;
}
int calc(int x,int y) {
return 1ll * ((fac[x] * inv[y]) % mod) * (inv[x - y]) % mod;
}
void get_inv() {
fac[0] = 1,inv[0] = 1;
for(int i = 1;i <= n;i++) {
fac[i] = 1ll * fac[i - 1] * i % mod;
inv[i] = fstpow(fac[i],mod - 2);
}
}
main() {
scanf("%I64d",&n);
get_inv();
int ans1 = 0;
for(int a,b,i = 1;i <= n;i++) {
a = 1ll * calc(n,i) * fstpow(-1,i + 1) % mod;
b = fstpow(3, (1ll * n * (n - i) + i) % (mod - 1));
ans1 = (ans1 + (1ll * a * b % mod)) % mod;
}
ans1 = 2 * ans1 % mod;
int ans2 = 0;
for(int t,b,a,i = 0;i < n;i++) {
a = 1ll * calc(n,i) * fstpow(-1,i + 1) % mod;
t = mod - fstpow(3,i);
b = (fstpow(t + 1,n) + mod - fstpow(t,n)) % mod;
ans2 = (ans2 + (1ll * a * b) % mod) % mod;
}
//int tmp =
printf("%I64d\n",(((ans1 + 1ll * ans2 * 3) % mod) + mod) % mod);
return 0;
}