基础算法_鸽巢原理+打表

题意:

给一个n*m的矩阵,每个小方格都可以取三种颜色。问有多少种染色方法可以使得矩阵中至少一对(x1,y1)与(x2,y2)满足
在这里插入图片描述
输入:
t,代表t组样例
每组样例输入n和m

输出:
染色方案数

思路:

打表 + 鸽巢原理

打表:可以手动打表(很难),也可以想办法代码进行打表

鸽巢原理:400个人一定有两个人在同一天生日(通俗易懂哈)

官方题解:
不妨假设n < m。考虑一个只有2行的矩阵。

由于我们只有3种颜色,只能产生9种不同的列组合。如果我们的列数超过9.

根据抽屉原理,我们必定能找到相同的两列。也就是说,当 max(n,m) > 9的时候,所有的染色方案都可以产生满足条件的矩阵。

对于更小的情况,我们可以暴力搜索来算出那些不满足题设的方案数。如果担心实现的效率,也可以打表。

代码实现:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int maxn = 5e6 + 5;
const ll mod = 1e9 + 7;
//打表???
ll qpow(ll a,ll b){
    ll res = 1;
    while(b){
        if(b & 1) res = (res * a) % mod;
        a = (a * a) % mod;
        b >>= 1;
    }
    return res % mod;
}
ll data[9][9] = {0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 15, 339, 4761, 52929, 517761, 4767849, 43046721, 387420489,
0, 339, 16485, 518265, 14321907, 387406809, 460338013, 429534507, 597431612,
0, 4761, 518265, 43022385, 486780060, 429534507, 792294829, 175880701, 246336683,
0, 52929, 14321907, 486780060, 288599194, 130653412, 748778899, 953271190, 644897553,
0, 517761, 387406809, 429534507, 130653412, 246336683, 579440654, 412233812, 518446848,
0, 4767849, 460338013, 792294829, 748778899, 579440654, 236701429, 666021604, 589237756,
0, 43046721, 429534507, 175880701, 953271190, 412233812, 666021604, 767713261, 966670169,
0, 387420489, 597431612, 246336683, 644897553, 518446848, 589237756, 966670169, 968803245};
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        ll n,m;
        scanf("%lld%lld",&n,&m);
        if(n == 1||m == 1){
            printf("0\n");
        }
        else if(n > 9||m > 9){
            ll ans = qpow(3ll,n * m);
            printf("%lld\n",ans);
        }
        else{
            n--;//手动写二维矩阵,为了对应好,n--
            m--;
            ll ans1 = data[n][m] % mod;
            printf("%lld\n",ans1);
        }
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值