Harmonious Rectangle(dfs 打表)

题意:

问有多少个n*m的012矩阵,存在至少一组 ( x 1 , x 2 ) ( y 1 , y 1 ) (x1,x2)(y1,y1) (x1,x2)(y1,y1)使得4个点 ( x 1 , y 1 ) ( x 1 , y 2 ) ( x 2 , y 1 ) ( x 2 , y 2 ) (x1,y1)(x1,y2)(x2,y1)(x2,y2) (x1,y1)(x1,y2)(x2,y1)(x2,y2)组成在这里插入图片描述
(0和1可以用2代替,也就是两列各自相同或者两行各自相同)

解析:

分析一下n*2:

∣ 0 , 0 ∣ |0,0| 0,0
∣ 0 , 1 ∣ |0,1| 0,1
∣ 0 , 2 ∣ |0,2| 0,2
∣ 1 , 0 ∣ |1,0| 1,0
∣ 1 , 2 ∣ |1,2| 1,2
∣ 2 , 0 ∣ |2,0| 2,0
∣ 2 , 1 ∣ |2,1| 2,1

得出当n或者m大于7时一定存在,所以我们只需要暴力求出n<8,m<8的情况即可

代码:

/*
 *  Author : Jk_Chen
 *    Date : 2020-12-25-12.46.27
 */
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define LD long double
#define rep(i,a,b) for(int i=(int)(a);i<=(int)(b);i++)
#define per(i,a,b) for(int i=(int)(a);i>=(int)(b);i--)
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define pill pair<int, int>
#define fi first
#define se second
void test(){cerr<<"\n";}
template<typename T,typename... Args>void test(T x,Args... args){cerr<<"> "<<x<<" ";test(args...);}
const LL _mod=1e9+7;
const int maxn=1e5+9;
const int inf=0x3f3f3f3f;
LL rd(){ LL ans=0; char last=' ',ch=getchar();
    while(!(ch>='0' && ch<='9'))last=ch,ch=getchar();
    while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
    if(last=='-')ans=-ans; return ans;
}
#define rd rd()
/*_________________________________________________________begin*/

LL Pow(LL a,LL b,LL mod=_mod){
    if(a>=mod)a%=mod;
    LL res=1;
    while(b>0){
        if(b&1)res=res*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return res;
}
/*_________________________________________________________Pow*/

LL ans[10][10];
int mp[10][10];
int n,m;

void dfs(int i,int j){
    if(i==n+1){
        ans[n][m]++;
        return;
    }
    rep(k,0,2){
        bool can=1;
        rep(_i,1,i-1)
            rep(_j,1,j-1){
                if(mp[_i][_j]==mp[_i][j]&&mp[i][_j]==k){
                    _i=i;can=0;break;
                }
                if(mp[_i][_j]==mp[i][_j]&&mp[_i][j]==k){
                    _i=i;can=0;break;
                }
            }
        if(can){
            mp[i][j]=k;

            int toi=i;
            int toj=j;

            if(j==m){
                toi++;
                toj=1;
            }
            else{
                toj++;
            }
            dfs(toi,toj);
        }
    }
}

void init(int _n,int _m){
    n=_n,m=_m;
    dfs(1,1);
}

LL A[8][8]={
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,66,390,1800,6120,13680,15120,
0,0,390,3198,13176,27000,13680,15120,
0,0,1800,13176,24336,4320,0,0,
0,0,6120,27000,4320,4320,0,0,
0,0,13680,13680,0,0,0,0,
0,0,15120,15120,0,0,0,0,
};

int main(){
//    rep(i,2,7)rep(j,2,7){
//        init(i,j);
//        //printf("%d,%d) %lld\n",i,j,ans[i][j]);
//    }
//    rep(i,1,7)rep(j,1,7){
//        printf("%lld%c",ans[i][j],",\n"[j==7]);
//    }
    int t=rd;
    while(t--){
        n=rd,m=rd;
        if(n==1||m==1){
            printf("%lld\n",0ll);
        }
        else if(n>7||m>7){
            printf("%lld\n",Pow(3,n*m));
        }
        else{
            printf("%lld\n",(Pow(3,n*m)+_mod-A[n][m])%_mod);
        }
    }
    return 0;
}

/*_________________________________________________________end*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值