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