HDU 6048 Puzzle(逆序数+等差数列)

传送门

题意:

 给你一个N*M大小的矩阵,表示一个“拼图”模型,这个拼图有N*M-1个块,现在有1~N*M-1个编号,给你一个P,每次取第1个,第1+P个,第1+2*P个,第1+3*P个……依次从上到下,从左到右填入到模型中,问是否可以通过有限次的移动使得编号按照1~N*M-1的顺序排列好,输出YES和NO。

思路:

原排列的写出来之后写成一排,这个序列的逆序数为偶数即“YES”,否则“NO”。


下面来求逆序数。
对于一个序列1,2,3,4.......n
给出一个p,一轮能取得的数是1,p+1,2*p+1....
一共取出的数的个数temp=(n-1)/p+1
比第一个数小且没取过的数(逆序数)是0,
比第二个数小且没取过的数(逆序数)是p-1
比第三个数小且没取过的数(逆序数)是2*(p-1)

上面的序列构成了一个等差数列,其和为(0+(temp-1)*(p-1))*temp/2


手动写出几项,发现对于每一次构造都满足上面的公式




循环求和即可求出


代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;

int main()
{
    int t;
    LL n,m,p,temp,sum,ans;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%lld%lld%lld",&n,&m,&p);
        sum=n*m-1;
        ans=0;
        while(sum>p)
        {
            temp=(sum-1)/p+1;///每轮的个数
            sum-=temp;
            ans+=(temp-1)*(p-1)*temp/2;///每轮构成的几个数构成等差数列,求和
        }
        if(ans&1)
            printf("NO\n");
        else
            printf("YES\n");
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值