其他分享
首页 > 其他分享> > [CF1228E]Another Filling the Grid

[CF1228E]Another Filling the Grid

作者:互联网

题目

传送门 to CF

传送门 to luogu

思路

首先考虑 d p \tt dp dp ,不行再换一个方法。

用 f ( x , y ) f(x,y) f(x,y) 表示,填了前 x x x 行,有 y y y 列还没有满足 min ⁡ = 1 \min=1 min=1 。转移则可枚举,这 y y y 列中有 i i i 列填了 1 1 1 ,所以有

f ( x + 1 , y − i )    +=    ( y i ) ( k − 1 ) y − i k n − y f ( x , y ) f(x+1,y-i)\;\text{+=}\;{y\choose i}(k-1)^{y-i}k^{n-y}f(x,y) f(x+1,y−i)+=(iy​)(k−1)y−ikn−yf(x,y)

特殊考虑这一行没有 1 1 1 的情况。所以 f ( x + 1 , y )    − =    f ( x , y ) ( k − 1 ) n f(x+1,y)\;-\text{=}\;f(x,y)(k-1)^{n} f(x+1,y)−=f(x,y)(k−1)n

即 f ( x , y ) = ∑ i = 0 n − y ( y + i i ) ( k − 1 ) y k n − y − i f ( x − 1 , y + i ) − f ( x − 1 , y ) ( k − 1 ) n f(x,y)=\sum_{i=0}^{n-y}{y+i\choose i}(k-1)^yk^{n-y-i}f(x-1,y+i)-f(x-1,y)(k-1)^{n} f(x,y)=i=0∑n−y​(iy+i​)(k−1)ykn−y−if(x−1,y+i)−f(x−1,y)(k−1)n

我没有找到很好的方式去优化它。大概只能做到 O ( n 3 ) \mathcal O(n^3) O(n3) 吧。

换个思路,用容斥计算有 a a a 行 b b b 列没有 1 1 1 的情况。所以答案为

∑ a = 0 n ∑ b = 0 n ( − 1 ) a + b ( n a ) ( n b ) ( k − 1 ) ( a + b ) n − a b k ( n − a − b ) n + a b = ∑ a = 0 n ( − 1 ) a ( n a ) ( k − 1 ) a n k ( n − a ) n ∑ b = 0 n ( − 1 ) b ( n b ) ( k − 1 ) b n − a b k a b − b n \begin{aligned} &\sum_{a=0}^{n}\sum_{b=0}^{n}(-1)^{a+b}{n\choose a}{n\choose b}(k-1)^{(a+b)n-ab}k^{(n-a-b)n+ab}\\ =&\sum_{a=0}^{n}(-1)^a{n\choose a}(k-1)^{an}k^{(n-a)n}\sum_{b=0}^{n}(-1)^{b}{n\choose b}(k-1)^{bn-ab}k^{ab-bn} \end{aligned} =​a=0∑n​b=0∑n​(−1)a+b(an​)(bn​)(k−1)(a+b)n−abk(n−a−b)n+aba=0∑n​(−1)a(an​)(k−1)ank(n−a)nb=0∑n​(−1)b(bn​)(k−1)bn−abkab−bn​

令 f ( x ) = ∑ i = 0 n ( − 1 ) i ( n i ) x i f(x)=\sum_{i=0}^{n}(-1)^i{n\choose i}x^i f(x)=i=0∑n​(−1)i(in​)xi

容易发现这就是二项式展开。当 2 ∣ n 2|n 2∣n 时 f ( x ) = ( x − 1 ) n f(x)=(x-1)^{n} f(x)=(x−1)n ;否则 f ( x ) = − ( x − 1 ) n f(x)=-(x-1)^{n} f(x)=−(x−1)n 。

但是答案会被巧妙的化简: ∑ a = 0 n ( − 1 ) a ( n a ) ( k − 1 ) a n k ( n − a ) n × f [ ( k − 1 k ) n − a ] \sum_{a=0}^{n}(-1)^{a}{n\choose a}(k-1)^{an}k^{(n-a)n}\times {\Large f}\left[\left(\frac{k-1}{k}\right)^{n-a}\right] a=0∑n​(−1)a(an​)(k−1)ank(n−a)n×f[(kk−1​)n−a]

复杂度 O ( n log ⁡ n ) \mathcal O(n\log n) O(nlogn) ,足以优秀地通过本题。

代码

#include <cstdio>
#include <iostream>
#include <vector>
using namespace std;
typedef long long int_;
inline int readint(){
	int a = 0; char c = getchar(), f = 1;
	for(; c<'0'||c>'9'; c=getchar())
		if(c == '-') f = -f;
	for(; '0'<=c&&c<='9'; c=getchar())
		a = (a<<3)+(a<<1)+(c^48);
	return a*f;
}

const int Mod = 1e9+7;
inline int qkpow(int_ b,int q){
	int a = 1;
	for(; q; q>>=1,b=b*b%Mod)
		if(q&1) a = a*b%Mod;
	return a;
}

const int MaxN = 252;
int jc[MaxN], inv[MaxN], n;
void prepare(){
	jc[1] = inv[1] = 1;
	for(int i=2; i<=n; ++i){
		jc[i] = 1ll*jc[i-1]*i%Mod;
		inv[i] = (0ll+Mod-Mod/i)*inv[Mod%i]%Mod;
	}
	for(int i=2; i<=n; ++i)
		inv[i] = 1ll*inv[i-1]*inv[i]%Mod;
	jc[0] = inv[0] = 1;
}
int getC(int x,int y){
	if(y < 0 || x < y) return 0;
	return 1ll*jc[x]*inv[y]%Mod*inv[x-y]%Mod;
}

int f(int x){
	x = qkpow(x-1,n);
	return (n&1) ? Mod-x : x;
}

int main(){
	n = readint(); int k = readint();
	prepare(); // prepare for C
	int invk = qkpow(k,Mod-2);
	int k_1n = qkpow(k-1,n);
	int one = 1; // k_1n ^ a
	int invkn = qkpow(invk,n);
	int two = qkpow(k,1ll*n*n%(Mod-1));
	int ans = 0;
	for(int i=0; i<=n; ++i){
		int c = (k-1ll)*invk%Mod;
		c = f(qkpow(c,n-i));
		c = 1ll*c*one%Mod*two%Mod;
		c = 1ll*c*getC(n,i)%Mod;
		if(i&1) ans = (ans+Mod-c)%Mod;
		else ans = (ans+c)%Mod;
		
		one = 1ll*one*k_1n%Mod;
		two = 1ll*two*invkn%Mod;
	}
	printf("%d\n",ans);
	return 0;
}

标签:int,CF1228E,1ll,bn,Filling,Grid,choose,sum,Mod
来源: https://blog.csdn.net/qq_42101694/article/details/111589719