天天看点

Palindromic Squares(枚举)

Palindromic Squares

Rob Kolstad

Palindromes are numbers that read the same forwards as backwards. The number 12321 is a typical palindrome.

Given a number base B (2 <= B <= 20 base 10), print all the integers N (1 <= N <= 300 base 10) such that the square of N is palindromic when expressed in base B; also print the value of that palindromic square. Use the letters 'A', 'B', and so on to represent the digits 10, 11, and so on.

Print both the number and its square in base B.

PROGRAM NAME: palsquare

INPUT FORMAT

A single line with B, the base (specified in base 10).

SAMPLE INPUT (file palsquare.in)

10
      

OUTPUT FORMAT

Lines with two integers represented in base B. The first integer is the number whose square is palindromic; the second integer is the square itself.

SAMPLE OUTPUT (file palsquare.out)

1 1
2 4
3 9
11 121
22 484
26 676
101 10201
111 12321
121 14641
202 40804
212 44944
264 69696      

   题意:

   输入M表示M进制,找出N在范围1到300(十进制)中所有N*N为回文串的数,输出N与N*N。比如当M=2时找出N在1~300(十进制)中,N*N为回文串的数,输出N和N*N,其中的N和N*N都用二进制来表示。

   思路:

   i从1循环到300,转换为N进制的操作封装在一个函数中,另外作为判断是否为回文串的操作封装在另一个函数中,最后在主函数的循环中直接调用两个函数即可判断出是否为回文串。M进制的M为1到20,说明最多用20进制来表示,则用一个数组来装M进制个位数的表示方式。

   总体思路就是:将a和a平方转化为M进制(倒着存)后判断a平方是否为回文串(余数判断),是则输出,不是则判断下一个数。

   AC:

/*
TASK:palsquare
LANG:C
ID:sum-g1
*/
#include<stdio.h>
#include<string.h>
int N,alength,blength;
int a[20],b[20];  
//a数组为还没平方时的数(已经转化为M进制)(倒序)
//b数组为a数平方后的数(已经转化为M进制)(倒序)
int change(int c)   
{
	int cs=c*c,i=1;
	while(c)  {a[i++]=c%N;c/=N;}
	alength=i-1;
	i=1;
	while(cs) {b[i++]=cs%N;cs/=N;}
	blength=i-1;
}
//change为改变成M进制的数,存的方式为倒序
int judge()
{
    int i,j;
    for(i=1,j=blength;i<=blength;i++,j--)
      if(b[i]!=b[j])  return 0;
    return 1;
}
//judge判断这个数是否为回文串,变量i从头开始向后遍历,变量j从尾开始向前遍历
//发现有一项不同就返回0,说明不同
int main()
{
FILE *fin =fopen("palsquare.in","r");
 FILE *fout=fopen("palsquare.out","w");	
int i,p;
	char k[20]="0123456789ABCDEFGHIJ";
//k数组为M进制的表示方式
	fscanf(fin,"%d",&N);
	for(i=1;i<=300;i++)
	{
		change(i);
		if(judge())
		{
			for(p=alength;p>=1;p--)  fprintf(fout,"%c",k[a[p]]);
//满足条件则输出a,记得从尾开始输出,因为前面是倒序存储的
                        fprintf(fout," ");
			for(p=blength;p>=1;p--)  fprintf(fout,"%c",k[b[p]]);
//满足条件输出a平方,同样的也是从尾部开始输出(也可以不倒序,因为是回文串)
			fprintf(fout,"\n");
		}
	}
	exit(0);
}      

   总结:

   字符数组的初始化为char k[20]="0123456789ABCDEFGHIJ"时编译器会通过不了,所以改用strcpy(k,"0123456789ABCDEFGHIJ")。但是,提交上去的时候strcpy(k,"0123456789ABCDEFGHIJ")则不能通过,所以改回用char k[20]="0123456789ABCDEFGHIJ",然后就AC了这道题了。

   考虑这题的时候思维真的很混乱,用数组存的话存进去的顺序是倒序的,后来想着想着,回文串既然是对称的,倒不倒序好像没关系……但是对于还没平方的数要倒序输出才行。现在想问题很容易将问题复杂化,其实细心想想,很多地方还是可以简化的。

    1.不需要开一个数组存倒序的,另外再开个数组存顺序的,输出的时候倒着输出就行了,判断的时候一个从前向后遍历,一个从后向前遍历,倒不倒序也没什么影响的;

    2.还有在比较是否对称的时候,只要有一个不满足相等的条件就返回False,不需要等全部都比较完才判断是Ture还是False;

    3.用几进制来表示可用开个数组来表示对应关系(M进制里面没有M数字表示,比如2进制中表示的数字中没2);

    4.判断是否对称不需要一定先转化为M进制表示的数才开始对称的,对这个数不断对M取余(当然每取完一次要/M)保存在数组后,就可以直接对这个数组进行判断是否对称了。如果用20进制表示的话,比如数63的平方3696(10进制),然后对3696不断取余变成一个20进制的数(变成9I9),用一个数组a[5](这个数组应该是int类型的)存着,那么就是a[1]=9,a[2]=19(I就是第19个表示数),a[3]=9(9跟9对称,19在中间)。这样的话,把20进制表示数对称转化为余数对称,这样一来就不用想那么多了,不需要另外找一个数组来存他们转换成M进制后的数再来判断是否为回文串了。

    这些细节和技巧的东西也要慢慢积累才行,不然代码会写得多又繁杂,当然也要保持清醒的头脑,才会想到那么多,有时候只会想着说要怎么解决一个题,然后就会忽略了很多可以运用技巧的地方。