USTCOJ1381 老式计算器 uva11549 (Set判重、Floyd判圈)

来源:互联网 发布:数据展示系统 编辑:程序博客网 时间:2024/06/10 22:37

题目链接: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位组成的整数。该函数有多中实现方式,见第三节。

解题思路一

将所有出现的k值存起来,并定义一个变量ans存储当前已知的k已取得的最大值。当新产生的k值已出现过,则退出循环,输出ans值。
代码实现,使用stl set存储所有可能的k值。如下:

/*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判圈算法求解。相关分析可参考:链表环的检测(Floyd判圈算法)

/*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;}

next函数实现

在具体的代码代码实现中,求解一个数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;}