题解 CF997C 【Sky Full of Stars】

直接求不好求,考虑用总方案数减去不合法方案数。设 \(f_{i,j}\) 为至少有 \(i\)\(j\) 列颜色相同的方案数,设 \(g_{i,j}\) 为恰好有 \(i\)\(j\) 列颜色相同的方案数,得:

\[\large f(x,y)=\sum_{i=x}^n\sum_{j=y}^n\binom{i}{x}\binom{i}{y}g(i,j) \]

然后发现其可以高维二项式反演,高维反演即为每个维度的反演系数直接乘起来,进行高维二项式反演得:

\[\large g(x,y)=\sum_{i=x}^n\sum_{j=y}^n(-1)^{i+j-x-y}\binom{i}{x}\binom{i}{y}f(i,j) \]

即答案为:

\[\large ans=3^{n^2}-g(0,0) \]

考虑计算 \(f\),得:

\[\large f(i,j) = \begin{cases} \binom{n}{i}\binom{n}{j}3^{(n-i)(n-j)+1} &ij \not = 0 \\ \\ \binom{n}{i+j}3^{n(n-i-j)+i+j} &ij=0,i+j \not =0 \\ \\ 3^{n^2} &i+j=0 \end{cases}\\ \]

当行列都存在相同颜色时,因为行列有交叉部分,所以其只能取同一种颜色,而只有行存在相同颜色或只有列存在相同颜色时,其颜色的选取时不受限制的。

然后计算 \(g(0,0)\)

\[\large\begin{aligned} g(0,0)&=\sum_{i=0}^n\sum_{j=0}^n(-1)^{i+j}f(i,j) \\ &=\sum_{i=1}^n\sum_{j=1}^n(-1)^{i+j}f(i,j)+2\sum_{i=1}^n(-1)^if(i,0)+f_{0,0} \end{aligned} \\ \]

因为第一个和式的原因,直接计算的复杂度是 \(O(n^2)\) 的,无法接受,考虑进行化简:

\[\large\begin{aligned} &\sum_{i=1}^n\sum_{j=1}^n(-1)^{i+j}f(i,j) \\ =&\sum_{i=1}^n\sum_{j=1}^n(-1)^{i+j}\binom{n}{i}\binom{n}{j}3^{(n-i)(n-j)+1} \\ =&\sum_{i=1}^n(-1)^{i}\binom{n}{i}\sum_{j=1}^n(-1)^{j}\binom{n}{j}3^{n^2-(i+j)n+ij+1} \\ =&3^{n^2+1}\sum_{i=1}^n(-1)^{i}\binom{n}{i}3^{-in}\sum_{j=1}^n\binom{n}{j}(-3^{i-n})^j \\ =&3^{n^2+1}\sum_{i=1}^n(-1)^{i}\binom{n}{i}3^{-in}((1-3^{i-n})^n-1) \\ \end{aligned}\\ \]

最终答案为:

\[\large ans=3^{n^2}-g(0,0)=-3^{n^2+1}\sum_{i=1}^n(-1)^{i}\binom{n}{i}3^{-in}((1-3^{i-n})^n-1)-2\sum_{i=1}^n(-1)^i\binom{n}{i}3^{n(n-i)+i} \]

#include<bits/stdc++.h>
#define maxn 1000010
#define p 998244353
using namespace std;
typedef long long ll;
template<typename T> inline void read(T &x)
{
    x=0;char c=getchar();bool flag=false;
    while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
    while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    if(flag)x=-x;
}
ll n,v1,v2;
ll fac[maxn],ifac[maxn];
ll qp(ll x,ll y)
{
    ll v=1;
    while(y)
    {
        if(y&1) v=v*x%p;
        x=x*x%p,y>>=1;
    }
    return v;
}
ll C(int n,int m)
{
    return fac[n]*ifac[m]%p*ifac[n-m]%p;
}
void init()
{
    fac[0]=ifac[0]=1;
    for(int i=1;i<=n;++i) fac[i]=fac[i-1]*i%p;
    ifac[n]=qp(fac[n],p-2);
    for(int i=n-1;i;--i) ifac[i]=ifac[i+1]*(i+1)%p;
}
int main()
{
    read(n),init();
    for(int i=1;i<=n;++i)
    {
        ll v=C(n,i)*qp(qp(3,i*n),p-2)%p*(qp((1-qp(qp(3,n-i),p-2)+p)%p,n)-1+p)%p;
        if(i&1) v1=(v1-v+p)%p;
        else v1=(v1+v+p)%p;
    }
    for(int i=1;i<=n;++i)
    {
        ll v=C(n,i)*qp(3,n*(n-i)%(p-1)+i)%p;
        if(i&1) v2=(v2-v+p)%p;
        else v2=(v2+v+p)%p;
    }
    printf("%lld",((-qp(3,(n*n+1)%(p-1))*v1%p+p)%p-2*v2%p+p)%p);
    return 0;
}
posted @ 2020-08-18 21:59  lhm_liu  阅读(462)  评论(0编辑  收藏  举报