【计数】 CF997C 【Sky Full of Stars】

skydogli

2021-01-20 10:33:58

Solution

这题好像直接做就好了? 如果单独考虑行的情况,大概大部分人都能用简单的容斥乱杀。当然,也可以钦定第 $i$ 行为第一次满足条件的行(也就是之前的行都不合法),这个东西求和的式子是: $$\sum_{i=1}^n (3^{n}-3)^{i-1}\times 3\times {(3^n)}^{n-i}$$ 前面式子是每行都有3种满足条件的情况不能选,然后这一行红绿蓝3种合法情况,后面随意。 而现在加入了列,我们只需要强制没有任何一行满足条件,再统计列的方案即可,这样就能保证不重不漏了。于是我们只要简单地限制一下行,用容斥做的话非常方便。 枚举 $i$ 列满足条件: $$\sum_{i=1}^n (-1)^{i-1}\binom{n}{i}f_i$$ 其中 $f_i$ 表示钦定前 $i$ 列满足条件的方案数,需要考虑这 $i$ 列是否都是同一颜色。 不同的贡献: $$(3^i-3)\times {(3^{n-i})}^{n}$$ 前面是选列的方案数后面是其他列可以任意选的方案数。 全部相同的贡献: $$3\times (3^{n-i}-1)^n$$ 枚举红绿蓝,然后每一列都不能全都是这个颜色。 $f_i$ 就是两个加起来了。 这题比较简单,就顺便讲讲这个容斥的正确性。 考虑任意一种有 $m$ 列符合条件的情况,他会在 $i=1$ 时统计 $\binom{m}{1}$ 次,在 $i=2$ 时统计 $\binom{m}{2}$ 次...在 $i=k$ 时统计 $\binom{m}{k}$ 次。(注意这个统计次数和上面的式子没有关系) 所以总的贡献是: $$\sum_{i=1}^m \binom{m}{i}(-1)^{i-1}$$ $$=-\sum_{i=1}^m \binom{m}{i}(-1)^{i}$$ $\binom{n}{0}(-1)^0$恒为 $1$,我们补进去。 $$=-(-1+\sum_{i=0}^m \binom{m}{i}(-1)^{i})$$ 后面的式子等于 $(1-1)^m$ (二项式定理) 考虑$0^0=1,0^i=0(i\neq0)$。 所以右边的式子在 $m\neq 0$ 时都是0。 于是我们发现每个合法情况的贡献都是 $1$ 。 那么我们就可以心安理得地切掉这题了。 ```cpp #include<bits/stdc++.h> using namespace std; #define int long long #define Mod 998244353 int read(){ int a=0,fh=1;char c=getchar(); while(c>'9'||c<'0'){if(c=='-')fh=-1;c=getchar();} while('0'<=c&&c<='9'){ a=a*10+c-48; c=getchar(); } return a*fh; } int ksm(int a,int x){ int ans=1,w=a; while(x){ if(x&1)ans=ans*w%Mod; w=w*w%Mod; x>>=1; } return ans; } #define MN 1000005 #define pii pair<int,int> #define mp make_pair #define x first #define y second int n; int pw[MN],fac[MN],dfac[MN],inv[MN]; int C(int m,int n){ if(m<n)return 0; return fac[m]*dfac[n]%Mod*dfac[m-n]%Mod; } signed main(){ n=read(); int tmp=ksm(3,n); pw[0]=1;for(int i=1;i<=n;++i)pw[i]=pw[i-1]*tmp%Mod; fac[0]=dfac[0]=fac[1]=dfac[1]=inv[1]=1; for(int i=2;i<=n;++i){ fac[i]=fac[i-1]*i%Mod; inv[i]=(Mod-Mod/i)*inv[Mod%i]%Mod; dfac[i]=dfac[i-1]*inv[i]%Mod; } int ans=0,w=tmp-3,buf=1; for(int i=1;i<=n;++i){ ans=(ans+buf*pw[n-i]*3)%Mod; buf=buf*w%Mod; } int iv=ksm(w,Mod-2); for(int i=1;i<=n;++i){ buf=buf*iv%Mod; int tmp=3*C(n,i)%Mod*ksm(ksm(3,n-i)-1,n)%Mod; tmp=(tmp+(ksm(3,i)-3)*C(n,i)%Mod*ksm(ksm(3,n-i),n))%Mod; tmp=tmp%Mod; if(i-1&1) tmp=Mod-tmp; ans=(ans+tmp)%Mod; } printf("%lld\n",ans); return 0; } ```