标题解释:名为分治算法,实为顺序结构。欲知何出此言,且听下文分解。
前言:这次考试稳(wan)了,这次考试班级排名保二(位数)了,但不管怎么说,还是要冷静下来。虽然明天就能出成绩了,但今晚还是开一道题。上题目:
[问题描述]
现给出正整数,求出的后四位。
[输入]
第一行一个正整数,表示有组数据,其中。
接下来行,每行一个正整数。
[输出]
共行,每个对应的结果占一行。如果不足四位,去掉前导零。
[样例输入]
3
5
28
792
[样例输出]
1051
81
5521
[数据规模与约定]
对于的数据,。
第一印象: ?是不是多打了个?这让人怎么算呀?淡定,淡定,开始分析。
这是一道分治算法题,至于的次方就要用到高精度算法了。我自己试着写了写,半个小时过去了代码还是一片狼藉,在这里就不展示了。我就另想思路。
我在上一期说过,事物的发展有其规律,这道题是不是也有规律?
既然只要求最后四位数,那我们就自始至终只考虑最后四位数。只有四位数,也就是说最多有种答案,那就必定存在循环。至于多少次一循环呢?我们不妨写个小程序试一下。
#include <cstdio>
int a = 2011, p;
int main() {
do {
a = a * 2011 % 10000;
p++;
}
while (a != 2011);
printf("%d", p);
}
跑一下程序,发现次一循环。换句话说,对取模后,得到的结果仍然相同!
能想到这里,问题就解决的差不多了——相当于把的范围从的次方缩小到了!现在还差一个小问题:高精度数怎么对取模?其实也很简单,我们可以先对取模(即取最后三位),再对取模,这样就会非常省事!
剩下的就来硬算吧!代码真的很好写。讲解版AC代码如下:
#include <cstdio>
#include <cstring>
int t, m, r, len;
char s[520];
int main() {
scanf("%d ", &t); // 注意这里要多读入一个空格
while (t--) {
r = 0; m = 1; // 初始化
gets(s);
len = strlen(s);
for (int i = 3; i > 0; i--) // 取最后三位数,当然也可能不足三位,此方法通用
if (len - i >= 0)
r = r * 10 + s[len - i] - '0';
r %= 500;
for (int i = 1; i <= r; i++)
m = m * 2011 % 10000; // 暴力开算
printf("%d\n", m);
}
return 0;
}
原版代码:
#include <cstdio>
#include <cstring>
int t, m, r, len;
char s[520];
int main() {
scanf("%d ", &t);
while (t--) {
r = 0;
m = 1;
gets(s);
len = strlen(s);
for (int i = 3; i > 0; i--)
if (len - i >= 0)
r = r * 10 + s[len - i] - '0';
r %= 500;
for (int i = 1; i <= r; i++)
m = m * 2011 % 10000;
printf("%d\n", m);
}
return 0;
}
并以简短的代码冲上本题排行榜第一(我这还是标准格式呢)。
这题就讲到这里啦!好了,现在我又陷入低沉的情绪了,毕竟这次考的啥也不是,以后是该好好学了,如果这样的话以后发布代码就会少了,但我对代码的热爱永远不会消散!最后,感谢大家的支持——我是汤圆,我们下期再见!