codeforces 997-C. Sky Full of Stars


题目链接

https://codeforces.com/contest/997/problem/C

题意

给一个n*n的矩阵,要往每个格子涂rgb三种颜色之一。问有多少种涂色方案,满足至少有一列或者一行的颜色是相同的。

分析

ans=至少有一行的+至少有一列的-至少有一行且有一列的

[ ans=2sum_{i=1}^{n} (-1)^{i+1} C^i_n imes 3^{(n-i)n} imes3^i -sum_{i=1}^{n}sum_{j=1}^{n}(-1)^{i+j}3 C_n^i C_n^j3^{(n-i)(n-j)} ]

式子中第二项有两层求和可以通过二项式定理优化到一维。

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn=1000050;
ll fact[maxn],inv[maxn];
const ll MOD=998244353;
ll Pow(ll x,ll n){
	ll ans=1,base=x%MOD;
	while(n){
		if(n&1) ans=ans*base%MOD;
		base=base*base%MOD;
		n>>=1;
	}
	return ans;
}
void init(){
	fact[0]=1;
	for(int i = 1; i < maxn; ++i)
		fact[i]=fact[i-1]*i%MOD;
	inv[maxn-1]=Pow(fact[maxn-1],MOD-2);
	for(int i = maxn-2; i >= 0; --i)
		inv[i]=inv[i+1]*(i+1)%MOD;
}
int main(){
	init();
	int n;
	cin>>n;
	ll ans=0;
    for(int i = 1; i <= n; ++i){
        ll t=fact[n]*inv[i]%MOD*inv[n-i]%MOD*Pow(3,(ll)n*(n-i)+i)%MOD;
        if(i%2==0) t=-t;
        ans=(ans+t)%MOD;
        if(ans>=MOD) ans-=MOD;
        else if(ans<0) ans+=MOD;
    }
    ans=ans*2%MOD;
	ll p=1;
	for(int i = 0; i < n; ++i){
		ll t=fact[n]*inv[i]%MOD*inv[n-i]%MOD*3%MOD*(Pow(1-p,n)-Pow(-p,n))%MOD;
		if(i%2==0) t=-t;
		p=p*3%MOD;
		ans=(ans+t)%MOD;
		if(ans>=MOD) ans-=MOD;
        else if(ans<0) ans+=MOD;
	}
	cout<<(ans%MOD+MOD)%MOD<<endl;
	return 0;
}

原文地址:https://www.cnblogs.com/sciorz/p/9254774.html