HDU 6048 Puzzle 逆序对 计数 发现基本操作

8数码问题的扩展,给定一个n*m的局面,问是否有解。局面按题目规则生成。

将此问题称作扩展8数码问题的话,通过观察基本操作可以发现,对于x,在只影响x右下角格子的前提下,我们一定可以移到指定的位置。这样我们可以依次将1,2,3,...等格子归位。只剩下右下角四个格子的顺序不定。严格的说,是(n,m-1)与(n-1,m)的格子不能确定是否恰好在其位置上。枚举最简单的2*2情况可以发现,将数字按照每行每列的顺序写成一个排列后,其逆序对为奇数的时候不可以归位,偶数的时候可以归位。这相当于,移到最后,如果右下角四个格子的逆序对数为偶数,整个问题有解,否则整个问题无解。

还可以发现,之前我们的任何操作都不会改变逆序对的个数,因为考虑:
1.空格的横向移动:排列不发生改变,逆序对奇偶性不改变;
2.空格的竖向移动:相当于做了(m-1)次交换,由于最后空格回到了右下角,即竖向交换的次数为偶数次,设为2K,则总体交换次数为2K*(m-1)次,也不改变逆序对的奇偶性。

故全图剩右下角四个格子没处理时,排列的逆序对奇偶性和原问题排列逆序对的奇偶性是一样的。可以推出,原问题逆序对奇偶性为偶数的时候,有解;反之无解。

在计算逆序对奇偶性的时候,对于每个放入的值,其后面比它小的数相当于留下的插空,这个在演算纸上模拟一下就可以发现,公式可以看代码。

#include <cstdio>
int T;
long long res,n,m,P;
int main()
{
    scanf("%d",&T);
    while (T--) {
        res=0;
        scanf("%I64d%I64d%I64d",&n,&m,&P);
        n=n*m-1;
        while (n>P) {
            long long t=(n+P-1)/P;
            res+=t*(t-1)*(P-1)/2LL;
            n-=t;
        }
        puts(res%2?"NO":"YES");
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值