对acm类似矩形的规律题的解法(以ZCMU1595和POJ1969为例讲解)

                                       ZCMU1595:TomCat要吃饭

Description

TomCat 是一次单身Cat,但是他有着很多的基友,每次吃饭都会QQ他的某一只基友,然而,他的基友Jerry 总是很墨迹。等待是无聊的,这时TomCat在学校的地上乱走,这时他发现地上有方块铺成的,他按照下图的规律走,现在无聊的TomCat想知道,他如果走了n步,他应该在什么位置,位置用坐标(x,y)表示。

Input

每次输入一个数n,n=0是输入结束(n<=2*10^9)

Output

输出坐标(x,y)

Sample Input

8 20 25 0

Sample Output

2 3 5 4 1 5

先说一下这一道题的解法:

我当时看到这一道题的时候,第一个感觉好像是小学里面的奥数曾经写过的,不过印象也不是特别深刻了,那只能重新找一下了,其实规律也非常好找的,我当时第一想到的就是x轴和y轴的边界,x轴的偶数序列不就是x的平方吗,y轴的奇数序列不就是y的平方吗,不过这种的话也不是很好找。最后看了看还是直接从对角线出发比较好。观察一下对角线的规律,n=(num)*(num-1)+1;后观察第奇数行和偶数行的递变规律,写下来就好;有一点比较重要的就是千万不要忘了第一步num的确定,即在第几行 (这个写在程序的第一行)。

/**********************************
这是一道规律规律性非常强的题目:
1.主要从对角线出发,观察一下对角线的规律,n=(num)*(num-1)+1;
2.然后观察第奇数行和偶数行的规律,写下来就好;
3.还有一点比较重要的就是千万不要忘了第一步num的确定,即在第几行 
**********************************/ 
#include<bits/stdc++.h>
int main()
{
   double s,n;
   long long num,a,b;//num表示目前该数字n在第几层,a表示在横向第几层,b表示在竖向第几层 
   while(scanf("%lf",&n)==1&&n!=0)//当程序输入n的时候也就停止了 
   {
       	num=sqrt(n);//确定给出数字在第几层         
   	   	if(num<sqrt(n))
		{
			num+=1;//如果开方后不是整数说明要后移一层
		}
  		if(num%2==0)//当n在偶数层的时候 
  		{
  			if(n==num*(num-1)+1)//如果在对角线上直接输出num num
          	printf("%lld %lld\n",num,num);
      		else if(n>num*(num-1)+1)//不在对角线上的是有规律的,根据大眼睛观察法可以找到规律
       		{
        		b=num-(n-num*(num-1)-1);
          		printf("%lld %lld\n",num,b);//第偶数行横向不变,向下变大 
       		}
       		else
       		{
           		a=num-(num*(num-1)+1-n);//横着来看 
           		printf("%lld %lld\n",a,num);
       		}
  		}
   		else//当n是奇数的时候,奇数的时候递变顺序刚好相反 
   		{
    	    if(n==num*(num-1)+1)//第一件事都是先将对角线进行打印 
    	    {
    	    	printf("%lld %lld\n",num,num);//相当于来说这个对角线其实就是一个矩阵的主对角线 
			}
        	else if(n>num*(num-1)+1)//当如果不在对角线的情况的时候,也是分两边进行讨论的 
       		{
       		 	b=num-(n-num*(num-1)-1);
        		printf("%lld %lld\n",b,num);
       		}
       		else
       		{
        	    a=num-(num*(num-1)+1-n);
           	    printf("%lld %lld\n",num,a);
       		}
   	 	}
   }
    return 0;
}
 

                                        POJ1969:Count on Canton

One of the famous proofs of modern mathematics is Georg Cantor's demonstration that the set of rational numbers is enumerable. The proof works by using an explicit enumeration of rational numbers as shown in the diagram below. 

1/1 1/2 1/3 1/4 1/5 ...

2/1 2/2 2/3 2/4

3/1 3/2 3/3

4/1 4/2

5/1

In the above diagram, the first term is 1/1, the second term is 1/2, the third term is 2/1, the fourth term is 3/1, the fifth term is 2/2, and so on.

 

Input

The input list contains a single number per line and will be terminated by endof-file.

Output

You are to write a program that will read a list of numbers in the range from 1 to 10^7 and will print for each number the corresponding term in Cantor's enumeration as given below.

Sample Input

3
14
7

Sample Output

TERM 3 IS 2/1
TERM 14 IS 2/4
TERM 7 IS 1/4

先讲一下这道题目的思路吧:

这道题其实我觉得跟上面的浙江中医药的那道题非常像,所以我也就把他放在一起了,可能将这个图形顺时针旋转45度后会比较好理解.

这样可能看着就更加舒服了,这是一个基于蛇形排列的,排列顺序为1,2,3,4,5的递增数列,而每一行出现的分子或者分母最大的数就是他的行数。先判断在第几行,然后接下来就是分奇偶,所谓奇偶其实就是分子和分母的递增序列刚好是相反的。

以下是代码:

/*******************************
这一道题目是一个找规律的题目:
这道题实际上找到规律后就会非常简单:
1.图形是基于蛇形的
2.每一行呈1,2,3,4,5等排列
3.观察奇偶行的规律,分子分母分别成相反方向变化 
******************************/ 
#include<iostream>
#include<cstdio> 
#include<string>
#include<cstring>
#include<algorithm> 
using namespace std;
int m=10000;//m表示最多的行数 
int main()
{
	int i,n,t,j,s;//n表示输进来的数字,t用来记在哪一行 
	while(scanf("%d",&n)!=EOF)
	{
		s=0;
		t=0;
		for(i=0;i<=m;i++)
		{
			if(n>i*(i+1)/2&&n<=(i+1)*(i+2)/2)//第几行的确定 
			{
				t=i+1;//t表示数字在第i行
				break;
			}
		}
		s=n-(t-1)*t/2;//s表示数字在第i行第几个,也就是第t行	
		if(t%2==0)//如果i在第偶数行 
		{
			printf("TERM %d IS %d/%d\n",n,s,t-s+1);
		}
		else if(t%2==1)//如果i在奇数行 
		{
			printf("TERM %d IS %d/%d\n",n,t-s+1,s);
		}
	}
	return 0;
}

这种规律题的话我做了的题目很多都是潜藏在对角线那里的,可能还有更加好的解题方法,欢迎大家在下面留言。

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值