题目大意
给定一个
n×m
的网格图。有
p
种颜色可以用来涂在网格中。
定义一个方案是不单调的,当且仅当任意两列网格图中的颜色种类数加起来超过
求不单调的方案数。
Data Constraint
n≤100,q≤p≤100,m≤109
题解
每一列的方案显然只与它前一列的方案有关。
设
f[i][j]
表示做完前
i
列,最后一列恰好选了
那么
f[i][k]+=f[i−1][j]∗trans[j][k]
。
现在要处理的就是
trans[j][k]
了,这个可以预处理。
先枚举
j,k
再考虑
j,k
颜色集合的交集
x
,
预处理出
trans
之后,再矩阵乘法一下即可。
SRC
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std ;
#define N 100 + 10
typedef long long ll ;
const int MO = 998244353 ;
struct Matrix {
ll Mat[N][N] ;
} trans , f , s , ret ;
ll fac[N] , _fac[N] , T[N] ;
int n , m , p , q ;
ll ans ;
Matrix operator * ( Matrix a , Matrix b ) {
memset( ret.Mat , 0 , sizeof(ret.Mat) ) ;
for (int i = 1 ; i <= p ; i ++ ) {
for (int j = 1 ; j <= p ; j ++ ) {
for (int k = 1 ; k <= p ; k ++ ) {
ret.Mat[i][j] = (ret.Mat[i][j] + a.Mat[i][k] * b.Mat[k][j] % MO) % MO ;
}
}
}
return ret ;
}
ll Power( ll x , int k ) {
ll s = 1 ;
while ( k ) {
if ( k & 1 ) s = s * x % MO ;
x = x * x % MO ;
k /= 2 ;
}
return s ;
}
ll C( int n , int m ) { return fac[n] * _fac[m] % MO * _fac[n-m] % MO ; }
Matrix PowerM( int k ) {
for (int i = 1 ; i <= p ; i ++ ) s.Mat[i][i] = 1 ;
while ( k ) {
if ( k & 1 ) s = s * trans ;
trans = trans * trans ;
k /= 2 ;
}
return s ;
}
int main() {
freopen( "color.in" , "r" , stdin ) ;
freopen( "color.out" , "w" , stdout ) ;
scanf( "%d%d%d%d" , &n , &m , &p , &q ) ;
fac[0] = _fac[0] = 1 ;
for (int i = 1 ; i <= max(n,p) ; i ++ ) {
fac[i] = fac[i-1] * i % MO ;
_fac[i] = Power( fac[i] , MO - 2 ) ;
}
for (int i = 1 ; i <= p ; i ++ ) {
T[i] = Power( i , n ) ;
ll sum = 0 ;
for (int j = 1 ; j < i ; j ++ ) {
sum = (sum + T[j] * C(i,j) % MO) % MO ;
}
T[i] = (T[i] - sum + MO) % MO ;
}
for (int i = 1 ; i <= min(n,p) ; i ++ ) {
for (int j = 1 ; j <= min(n,p) ; j ++ ) {
for (int x = max(i+j-p, 0) ; x <= min(i,j) ; x ++ ) {
if ( i + j - x < q ) continue ;
trans.Mat[i][j] = (trans.Mat[i][j] + C(i,x) * C(p-i,j-x) % MO * T[j] % MO) % MO ;
}
}
}
for (int i = 1 ; i <= p ; i ++ ) f.Mat[1][i] = C(p,i) * T[i] % MO ;
f = f * PowerM( m - 1 ) ;
for (int i = 1 ; i <= p ; i ++ ) ans = (ans + f.Mat[1][i]) % MO ;
printf( "%lld\n" , ans ) ;
return 0 ;
}
以上.