题目链接:http://acm.ustc.edu.cn/ustcoj/problem.php?id=1381
题目来源:uva11549
题目:对于给定的n和k,求k平方,取其高n位数赋值给k,如是不断平方,给出这一运算过程中k可能取到的最大值。
题目分析:显然,对于一个n位整数而言,其可能的取值是有限的,因此上述过程必然出现循环。我们只要在平方过程中得到此前出现过的k值,就表示已经遍历了所有可能的k值。
程序头代码如下
#include<iostream> #include <cstdio> #include <cstdlib> using namespace std;以下两中解法均使用int next(int n, int k)函数来求解k平方的高n位组成的整数。该函数有多中实现方式,见第三节。
/*STL Set判重 *by: lance*/ int main() { int t; set<int> result; scanf("%d", &t); while (t--) { result.clear(); int n, k; scanf("%d%d", &n, &k); int ans = k; while (result.find(k) == result.end()) { if (ans < k) ans = k; result.insert(k); k = next(n, k); } printf("%d\n", ans); } return 0; }
/*Floyd判圈算法*/ int main() { int T; cin >> T; while(T--) { int n, k; cin >> n >> k; int ans = k; int k1 = k, k2 = k; do { k1 = next(n, k1); // 小孩1 k2 = next(n, k2); // 小孩2,第一步 if(k2 > ans) ans = k2; k2 = next(n, k2); // 小孩2,第二步 if(k2 > ans) ans = k2; } while(k1 != k2); // 追上以后才停止 cout << ans << endl; } return 0; }
在具体的代码代码实现中,求解一个数k的平方的高n位数有多种解法。我们定义该函数为int next(int n, int k)。如下是该函数的几种可能的实现。
/*方案一: *by: Rujia Liu*/ int buf[100]; int next(int n, int k) { if(!k) return 0; long long k2 = (long long)k * k; int L = 0; while(k2 > 0) { buf[L++] = k2 % 10; // 分离并保存k2的各个数字 k2 /= 10; } if(n > L) n = L; k = 0; for(int i = 0; i < n; i++) // 把前min{n,L}位重新组合 k = k * 10 + buf[--L]; return k; }
/*方案二: * by:ustczz*/ int next(int n, int k) { char str[100] = {0}; //初值为零 long long k2 = (long long)k * k; sprintf(str,"%lld",k2); //整数转化为字符串 str[n]='\0';//截取n位 k=atoi(str);//字符串转化为整数 return k; }
/*方案三: *by: 54whao *by: lance*/ long long pow10(int e) { long long p = 1; while (e--) p *= 10; return p; } int next(int n, int k) { /*通过将变量声明为“静态存储类型”, 使其可以记录函数上一次调用时的值 从而避免pow10的重复调用 */ static int nflag = -1; static long long p; if (nflag != n) { nflag = n; p = pow10(n); } long long k2 = (long long)k * k; while (k2 >= p) k2 /= 10; k = k2; return k; }