2020-08-19

http://icpc.upc.edu.cn/problem.php?cid=2550&pid=6

题目描述

Rainy7 一天醒来,发现自己进入了魔法世界。

一道大门矗立在 Rainy7 面前,似乎需要密码解锁。

Rainy7 经过一番查找后,找到了密码对应的问题:在n×m的棋盘上摆放两个不同颜色的皇后,使得它们能够相互攻击,总共有多少种摆法?

我们称两个皇后能够相互攻击,当且仅当它们在同一行或同一列或同一斜线上。

她只用了114514-1919810 s就解决了问题并打开了大门,于是把问题交给了您。

输入

第一行一个整数t,表示数据组数。
接下来t行,每行两个正整数n,m,表示棋盘的长和宽。

输出

t行,每行一个数,表示方案数。
由于这个数可能很大,您只要输出它对109+7取模的结果就可以了。

样例输入

【样例1】
1
2 2
【样例2】
1
114514 114514
【样例3】
2
165528 123456
132435 423153

样例输出

【样例1】
12
【样例2】
587308676
【样例3】
718509545
475373430

提示

样例1解释
如图所示:

对于20%的数据,1≤n,m≤50,1≤t≤10
对于50%的数据,1≤n,m≤300
对于70%的数据,1≤n,m≤5000
对于100%的数据,1≤n,m≤5×105,1≤t≤5000
本题部分数据卡常,请注意常数优化

解析

这道题目可以分为三种情况来讨论,横竖和对角线,横和竖都比较简单,结果为nm(n+m-2),对角线上推到见下图:
在这里插入图片描述

#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
ll n,m;
ll mul(ll a,ll b)
{
    ll sum1=0;
    ll sum2=a;
    while(b!=0)
    {
        if(b%2==1)
            sum1=(sum1+sum2)%mod;
        sum2=(sum2+sum2)%mod;
        b=b/2;
    }
    return sum1;
}
int main()
{
    ll t;
    scanf("%lld",&t);
    while(t--)
    {
        ll ans=0;
        scanf("%lld%lld",&n,&m);
        if(n>m)
            swap(n,m);
        ans+=mul(n*m,n+m-2);
        ll k1=n*(n-1)*2;
        ll k2=3*m-n-1;
        if(k1%3==0)
            k1=k1/3;
        else if(k2%3==0)
            k2=k2/3;
        ans+=mul(k1,k2);
        printf("%lld\n",ans%mod);
    }
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值