HDU 6048 Puzzle(思维以及爆int引发的思考)

Puzzle

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 491    Accepted Submission(s): 267


Problem Description
A Jigsaw puzzle contains N*M-1 pieces of jigsaws in a N rows*M columns rectangular board.Each jigsaw has a distinct number from 1 to N*M-1.Li is a naughty boy,he wants to arrange the board in his unique way.At the beginning,he picks all N*M-1 jigsaws out and put them on the table and then he will put them back to the board respecting the following steps:
1.Sorting all the remaining jigsaws on the table in ascending order.
2.Picking out the 1st ,the P+1 th ,the 2*P+1 th,......the n*P+1 th jigsaws and put them back to the blank area in the board one by one from the top row to the bottom row,from the left column to the right column.
3.if there are jigsaws remained on the table,back to step 1.
After he arranging the board,it’s obvious that there’s only one blank area located at the bottom-right corner.
Your task is to make the numbers on jigsaws sorted with every row and every column in ascending order(From left to right,top to bottom),and the blank area should be located at the bottom-right corner in the end.Each step you can move the blank area’s neighboring jigsaws(which share a common side with the blank area) towards the blank area.It’s really a difficult question,so you need to write a program to judge whether it is possible to complete the task.



 

Input
The first line contains an integer T(T<=100),which represents the number of test cases.
Following T lines,each line contains three integers N,M,P(2<=N,M<=1000;1<=P<=N*M-2).
 

Output
For each test case,print “YES” in a separate line if it is possible to complete the task ,otherwise please print “NO”.
 

Sample Input
  
  
3 3 2 3 3 2 4 999 999 1
 

Sample Output
  
  
YES NO YES
 
题意: n*m的格子中把1~n*m-1个数以从上到下从左到右的方式每次放置的数是 1~n*m-1中的第一个,第p+1个,第2*p+1个…….,放完一轮后再以这个方式放置, 判断这样放置的数字能否移动成从左到右从上到下依次排列的数
思路:

      a

      b

      x

      x

      x

     

对于2*3的任意排列总能是得a,b移动到如图位置
所以对于任意n*m的序列能取其中2*3的部分
移动到期望的样子
而对于移动上下移动和左右移动不改变
从原序列中以每一行取得数的逆序数
再对最后2*3的排列方式可知逆序数为偶时YES为奇时为NO
再由题意得排列方式可知,逆序数是以等差数列出现的
p-1为公差,项数为(num-1)/p+1,用求和公式就可求出逆序数
原来写的时候利用对2取模来判断奇偶
即如下代码居然wa掉了
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
const int mod=1000000007;
using namespace std;
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,m,p;
        scanf("%d%d%d",&n,&m,&p);
        int num=n*m-1;
        int cot=0;
        while(num>p)
        {
            int tmp=(num-1)/p+1;
            cot+=tmp*(tmp-1)/2*(p-1);
            num-=tmp;
        }
        if(cot%2==1)
            printf("NO\n");
        else
            printf("YES\n");
    }
    return 0;
}
最后看了标程,他也是用%2的方式判断奇偶的,但是他if,else这里反了一下
	if(cot%2)
            printf("NO\n");
        else
            printf("YES\n");
去掉了==1的这样判断情况
最后发现是在求和的时候爆了int类型,最后这个cot变成了负数,负数%2时奇数是=-1的,而且好像数据爆int的时候奇偶性并不改变所以标程那样也能过,最好的办法还是都改成long long了,还有操作就是和2进行&与操作
所以这题有神奇的几种写法
        if(cot%2==1||cot%2==-1)
            printf("NO\n");
        else
            printf("YES\n");

        if(cot%2==0)
            printf("YES\n");
        else
            printf("NO\n");

        if(cot&1)
            printf("NO\n");
        else
            printf("YES\n");

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
const int mod=1000000007;
using namespace std;
 long long n,m,p;
int main()
{
    long long t;
    scanf("%lld",&t);
    while(t--)
    {
        scanf("%lld%lld%lld",&n,&m,&p);
        long long num=n*m-1;
        long long cot=0;
        while(num>p)
        {
            long long tmp=(num-1)/p+1;
            cot+=tmp*(tmp-1)/2*(p-1);
            num-=tmp;
        }
        if(cot%2==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、付费专栏及课程。

余额充值