1. 程式人生 > 實用技巧 >CF997C Sky Full of Stars

CF997C Sky Full of Stars

CF997C Sky Full of Stars

40分鐘一波亂搞居然自己做出來了,開心!

答案是顯然可以轉化成:\(\rm{總方案數-沒有任何一行或一列同色的方案數}\)

為啥這麼化呢。。。顯然後面那個東西比直接算答案簡潔吧。

沒有任何一行一列,就是恰好 \(0\)\(0\) 列同色,強行把 恰好 拉出來反演掉。

\(g(x,y)\) 表示欽定 \(x\)\(y\) 列同色得到的方案數,\(f(x,y)\) 表示至少 \(x\)\(y\) 列同色的方案數

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

高維二項式反演的公式就是上面那玩意,瞎猜都能猜出來,事實上就是對的/cy。

但是不知道也沒關係,因為這題只要求 \(g(0,0)\) ,所以可以直接容斥而不用管擴充套件性這麼強的結論,我就是容斥想的,做完之後看題解看到了上面那個結論。

\[\sum_{i=0}^{n}\sum_{j=0}^{n}(-1)^{i+j}\binom{n}{i}\binom{n}{j}f(i,j) \]

首先得想個辦法把 \(f(x,y)\) 表示出來。

分成兩部分考慮,一部分是任選同色的 \(x\)\(y\) 列,一部分是在這 \(x\)\(y\) 列之外的格子。

  • 第一部分

    • 如果 \(x>0,y>0\)
      ,那麼這 \(x\)\(y\) 列必然同色,方案數乘 \(3\)
    • 如果 \(x=0\ or \ y=0\) ,那麼要麼全是行,要麼全是列,顏色隨便取,所以方案數乘 \(3^{x+y}\)
  • 第二部分

    剩餘格子個數應該是 \((n-x)(n-y)\) ,因為有 \(x\)\(y\) 列被佔用了。所以方案數乘上 \(3^{(n-x)(n-y)}\)

整合一下:

\[f(x,y)= \begin{cases} 3\times 3^{(n-x)(n-y)}\quad(x>0,y>0)\\ 3^{x+y}\times 3^{(n-x)(n-y)}\quad (x=0\ or\ y=0) \end{cases} \]

然而到此為止還是 \(O(n^2)\) 級別的複雜度。(有可能帶單隻快速冪 \(\log\) ,但是無關緊要,下同)

\(f(x,y)\)\(g(x,y)\) 的式子裡大力帶入然後整理。由於 \(x=0\ or\ y=0\) 的情況數很少,暴力 \(O(n)\) 算都可以,所以直接算 \(x>0,y>0\) 的情況了。

我是特判了 \(i=0\) 的情況,\(O(n)\) 計算,然後列舉 \(i\) 的過程中再特判 \(j=0\) 的情況的。

\[\text{原式}=\sum_{i=1}^{n}(\sum_{j=1}^{n}\binom{n}{i}\binom{n}{j}(-1)^{i+j}\times3\times3^{(n-i)(n-j)})+(-1)^{i+1}\times3^{i}\times 3^{(n-i)n}\\ =\sum_{i=1}^{n}\binom{n}{i}(-1)^{i}((\sum_{j=1}^{n}\binom{n}{j}(-1)^{j}\times 3\times 3^{(n-i)(n-j)})+(-1)^{i+1}\times 3^i\times 3^{(n-i)n}) \]

不知道你看出來了啥沒有,反正我看了大概1分鐘就會做了(

現在瓶頸就是下面這玩意對吧,把這個算出來就可以 \(O(n)\) 了。

\[\sum_{j=1}^{n}\binom{n}{j}(-1)^{j}\times 3\times 3^{(n-i)(n-j)}) \]

或許式子應該寫的更好看一點?令 \(t=3^{n-i}\)

\[3\sum_{j=1}^{n}\binom{n}{j}(-1)^{j}t^{n-j} \]

直接二項式定理就好了,不要忘記 \(j=0\) 的情況要減掉。

\[3(t-1)^n-t^n \]

#define mod 998244353
const int N=1000005;
namespace math{
int fac[N],ifc[N];
inline int qpow(int n,int k){int res=1;for(;k;k>>=1,n=1ll*n*n%mod)if(k&1)res=1ll*n*res%mod;return res;}
void fmod(int&x){x-=mod,x+=x>>31&mod;}
int comb(int n,int m){return n<m?0:1ll*fac[n]*ifc[m]%mod*ifc[n-m]%mod;}
void initmath(const int&n=N-1){
	fac[0]=1;for(int i=1;i<=n;++i)fac[i]=1ll*i*fac[i-1]%mod;
	ifc[n]=qpow(fac[n],mod-2);for(int i=n-1;i>=0;--i)ifc[i]=1ll*(i+1)*ifc[i+1]%mod;
}
}
using math::qpow;
using math::fmod;
int n,ans;
int f(int x,int y){
	return 1ll*qpow(3,1ll*(n-x)*(n-y)%(mod-1))*((!x||!y)?qpow(3,x+y):3)%mod;
}
signed main(){
	math::initmath();
	n=read();
	for(int i=1;i<=n;++i){
        const int t=qpow(3,n-i);
        int res=3ll*(qpow(t-1,n)-qpow(t,n)+mod)%mod;
        fmod(res+=1ll*qpow(t,n)*qpow(3,i)%mod);
        fmod(ans+=1ll*math::comb(n,i)*(i&1?mod-res:res)%mod);
    }
    for(int i=0;i<=n;++i)fmod(ans+=1ll*math::comb(n,i)*(i&1?mod-f(0,i):f(0,i))%mod);
	fmod(ans=qpow(3,1ll*n*n%(mod-1))-ans+mod);
	cout<<ans<<'\n';
}