sicily 1203 The Cubic End

summary

:

好不容易才想要刷道题,居然碰上了这么一道蛋疼的题,刚开始没看懂题(英语不好), 去查了单词才看懂了,然后想了半天没想出来,还是去看人家的解题报告才有了一些 灵感,水到爆了,我靠!

解题思路

题目意思是,输入一个数a的字符串,而且最后一个数必然是{1, 3, 7, 9}中的一个, 求一个位数不超过数a的数b,使得b^3的尾数是a。^

显然,要得到一个数的最后一位,模10,同理,要得到最后2位,模20,..., 我居然还去搜了一下怎么得到一个数的尾数,结果找到了一篇五年级奥数的培训文章 (这不是赤裸裸地鄙视吗???)。

于是,我们可以从个位开始匹配,刚开始就是{1, 3, 7, 9}中的一个,然后匹配十 位,再是百位,一直到匹配完。

举个例子:对于123, 因为一个数的立方的个位是3,所以这个数的个位必然是7, 然后我们加10, 判断17的立方模100是不是23,发现不是,继续下去,一直到 47时发现满足条件,现在判断147的立方模1000是不是123,发现不是,继续下去, 一直到947时发现满足条件。

方法是这样,但是有一些效率的问题,如果先算立方再再模,必然会很慢,而且可能 会溢出,于是需要用到数论的知识:

a^3 % m = (((a * a) % m) * a) % m

在这个题中,因为a肯定比m要小,所以没必要先求模,直接相乘了(求模是很慢的)。

最后一个大问题,当到达10位数时,long long已经放不下了,会溢出。怎么解决这 个问题呢?我看网上有很多人用高精度做,写了一大堆代码,蛋疼死了!我是学了数论 之后才想起来做题的,于是刚好可以用到"快速乘法 ",不用原本的乘法,自己写一个, 在相乘的时候,不断地取模,这样就能保证不溢出了。

代码

1:  #include <stdio.h>
2:  #include <math.h>
3:  #include <string.h>
4:  
5:  long long mul(long long left, long long right, long long power)
6:  {
7:      long long result;
8:  
9:      result = 0;
10:      while (left >= 1) {
11:          if (left & 1) {
12:              result += right;
13:          }
14:          right <<= 1;
15:          if (right > power) {
16:              right %= power;
17:          }
18:          left >>= 1;
19:      }
20:      if (result > power) {
21:          result %= power;
22:      }
23:      return result;
24:  }
25:  
26:  long long cube(long long base, long long power)
27:  {
28:      return mul(mul(base, base, power), base, power);
29:  }
30:  
31:  int main(int argc, char *argv[])
32:  {
33:      int c, len, i;
34:      long long result, rem, power, step;
35:      char str[11];
36:  
37:      scanf("%d", &c);
38:      while (c--) {
39:          scanf("%s", str);
40:          len = strlen(str);
41:          result = rem = str[len - 1] - '0';
42:          if (result == 3) {
43:              result = 7;
44:          } else if (result == 7) {
45:              result = 3;
46:          }
47:          power = 10;
48:          for (i = len - 2; i >= 0; i--) {
49:              rem += power * (str[i] - '0');
50:              step = power;
51:              power *= 10;
52:              if (len == 10 && i == 0) {
53:                  while (cube(result, power) != rem) {
54:                      result += step;
55:                  }
56:                  break;
57:              }
58:              while (((((result * result) % power) * result) % power) != rem) {
59:                  result += step;
60:              }
61:          }
62:          printf("%lld\n", result);
63:      }
64:  
65:      return 0;
66:  }