USACO打怪升级 (三): Your Ride Is Here

It is a well-known fact that behind every good comet is a UFO. These UFOs often come to collect loyal supporters from here on Earth. Unfortunately, they only have room to pick up one group of followers on each trip. They do, however, let the groups know ahead of time which will be picked up for each comet by a clever scheme: they pick a name for the comet which, along with the name of the group, can be used to determine if it is a particular group's turn to go (who do you think names the comets?). The details of the matching scheme are given below; your job is to write a program which takes the names of a group and a comet and then determines whether the group should go with the UFO behind that comet.


Both the name of the group and the name of the comet are converted into a number in the following manner: the final number is just the product of all the letters in the name, where "A" is 1 and "Z" is 26. For instance, the group "USACO" would be 21 * 19 * 1 * 3 * 15 = 17955. If the group's number mod 47 is the same as the comet's number mod 47, then you need to tell the group to get ready! (Remember that "a mod b" is the remainder left over after dividing a by b; 34 mod 10 is 4.)


Write a program which reads in the name of the comet and the name of the group and figures out whether according to the above scheme the names are a match, printing "GO" if they match and "STAY" if not. The names of the groups and the comets will be a string of capital letters with no spaces or punctuation, up to 6 characters long.


题目大意: UFO可以从地球带一些人去其他彗星,他们有一个规则,去其他星球的人以组为单位,每个组有个名字,这个组将要前往的彗星也有个名字,只有这两个名字满足一个关系,才可以前往,否则只能呆在地球上了。
    名字的匹配规则是: 名字可以转成一个数字,名字的每个字母都有个值,A是1,Z是26,名字转成的数字是名字每个字母值的积,例如“USACO”就是21 * 19 * 1 * 3 * 15 = 17955,组名和彗星名所代表的数字都是按照这个规则进行计算,最后,分别让组名所代表的数字以及彗星名代表的数字对47求余,如果两者的余数相同,就能前往该彗星,否则只能呵呵了。

INPUT FORMAT
Line 1: An upper case character string of length 1..6 that is the name of the comet.
Line 2: An upper case character string of length 1..6 that is the name of the group.

OUTPUT FORMAT
A single line containing either the word "GO" or the word "STAY".

分析:
    题目虽然有点长,但是只要认真看,还是很容易看懂,而且也可以说非常简单,不需要什么特殊算法。

首先给出我当时通过的代码

/*
 ID: fuchenc1
 PROG: ride
 LANG: C++ 
*/

#include <fstream>
#include <string>
#include <iostream>
using namespace std;
int  CalculateName(const string& strName)
{
  int len=strName.length(),res=1;
  for(int i=0;i<len;i++)
  {
      res*=((char)strName[i]-'A'+1);	
  }	
  return res;
}
int main()
{

   ifstream fin("ride.in");
   ofstream fout("ride.out");
   string strGroupName,strComtName,answer="STAY";
   fin>>strGroupName>>strComtName;
   if((CalculateName(strGroupName)%47)==(CalculateName(strComtName)%47))
   {
   	  answer="GO";
   }  
   fout<<answer<<endl;
   return 0;
}
 

  接下来是我通过测试后,题目给出的参考答案:

#include <stdio.h>
#include <ctype.h>

int
hash(char *s)
{
	int i, h;

	h = 1;
	for(i=0; s[i] && isalpha(s[i]); i++)
		h = ((s[i]-'A'+1)*h) % 47;
	return h;
}

void
main(void)
{
	FILE *in, *out;
	char comet[100], group[100];  /* bigger than necessary, room for newline */

	in = fopen("input.txt", "r");
	out = fopen("output.txt", "w");

	fgets(comet, sizeof comet, in);
	fgets(group, sizeof group, in);

	if(hash(comet) == hash(group))
		fprintf(out, "GO\n");
	else
		fprintf(out, "STAY\n");
	exit (0);
}

参考答案当中有一个亮点,就是这行代码:
 

h = ((s[i]-'A'+1)*h) % 47;

    参考答案并不是将字符串中每个字母所代表的数字相乘之后,再对总结果进行求余,相反,它是利用每个字母所代表的数字乘以上次所求得的余数,之后再进行求余,其实就是利用这样一个数学性质:
    
      (A*B)%C=(A*(B%C))%C;

利用这个方法有个非常大的好处,不容易产生数据溢出,因为如果是将各个字母的数直接相乘之后,再对总结果求余,在字母非常多的时候,有可能求出来的积早就超过了整型所能表示的最大范围了,而采用参考答案给出的方法,就不会产生这种问题。当然这道题最多只有6个字母,因此也不会产生这个问题。

 所以通过这道题应该学习到求余的这个小技巧: (A*B)%C=(A*(B%C))%C。




  

你可能感兴趣的:(算法,USACO)