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

来源:互联网 发布:算法工程师 待遇 编辑:程序博客网 时间:2024/06/05 03:39

传送门

题意:

 给你一个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;}


原创粉丝点击