[ICPC2020 Nanjing R] Harmonious Rectangle 题解
题解来源于一位和我组队且不愿透露姓名的好兄弟。
这个题有点类似于 2018 年考过的填数游戏。
首先考虑正难则反,也即考虑有多少染色不存在这样的子矩形。注意到,这样的子矩形的特征是两个同色格子在一行或者一列,另两个同色格子在一行或者一列。
所以,这样的矩阵必然满足,对于同行的两个同色格子,这两行其他列的对应位置两个格子必然不一样,列同理。
于是我们直接考虑某一行一种颜色的鸽子就好了,显然一行的某种颜色的格子不可能超过四个,由抽屉原理可以知道,必然在其他行会存在一个同色对,于是一行同色格子最多三个。然而只给了红黄蓝三种颜色,再用一次抽屉原理,当矩形的长或宽超过
然后写个爆搜就好了。不要认为最多可能状态有
记得特判
代码
#include<bits/stdc++.h>
using namespace std;
typedef int ll;
typedef long long int li;
const ll MAXN=3e5+51,MOD=1e9+7;
ll test,n,m,res;
ll c[15][15];
inline ll read()
{
register ll num=0,neg=1;
register char ch=getchar();
while(!isdigit(ch)&&ch!='-')
{
ch=getchar();
}
if(ch=='-')
{
neg=-1;
ch=getchar();
}
while(isdigit(ch))
{
num=(num<<3)+(num<<1)+(ch-'0');
ch=getchar();
}
return num*neg;
}
inline ll qpow(ll base,ll exponent)
{
ll res=1;
while(exponent)
{
if(exponent&1)
{
res=(li)res*base%MOD;
}
base=(li)base*base%MOD,exponent>>=1;
}
return res;
}
inline void solve()
{
n=read(),m=read(),n>m?swap(n,m):(void)1;
if(n==1||m==1)
{
return (void)puts("0");
}
if(n>=8||m>=8)
{
return (void)printf("%d\n",qpow(3,n*m));
}
printf("%d\n",(qpow(3,n*m)-c[n][m]+MOD)%MOD);
}
int main()
{
test=read();
c[2][2]=66,c[2][3]=390,c[2][4]=1800,c[2][5]=6120,c[2][6]=13680,c[2][7]=15120;
c[3][3]=3198,c[3][4]=13176,c[3][5]=27000,c[3][6]=13680,c[3][7]=15120;
c[4][4]=24336,c[4][5]=c[5][5]=4320;
for(register int i=1;i<=test;i++)
{
solve();
}
}