UVA11549计算器谜题

题意:
       有一个计算机只能保留数字的前n位,你有一个数字k(k<=9),反复平方后在计算机上显示的最大数字是多少。


思路:
      显然这个题目是有循环节的,为什么有循环节?首先我们看下k<=9那么也就是说所有的答案都是9位数之内的,也就是说才几亿呗,最慢几亿次之后必然循环啊,这样我们就可以不停得枚举,然后碰到循环节的时候就不枚举了,怎么样找循环节,一开始想的是只记录第一个,然后等第一个再次出现的时候就直接break结果果断错了,他有可能是类似这样的循环节1 2 3 4 5 4 5 4 5.....循环节是4 5,这种的,所以第一种方法失败了,但是我们可以用最笨的方法去记录,就是开一个容器,我开的是map,记录每个数字是否出现过,提交之后虽然ac了但感觉容器挺耗时的,然后又写了个书上说的那个Floyd判圈,结果果然快了很多,一下是两种方法的代码。




Floyd判圈


#include<stdio.h>


int mk[15];


void inint()
{
     mk[0] = 1;
     for(int i = 1 ;i <= 9 ;i ++)
     mk[i] = mk[i-1] * 10;
}


long long next(int n ,int a)
{
    long long now = (long long)a * (long long)a;
    while(now >= mk[n])
    now /= 10;
    return int(now);
}


int main ()
{
   int t ,n ,m ,Ans;
   inint();
   scanf("%d" ,&t);
   while(t--)
   {
       scanf("%d %d" ,&n ,&m);
       Ans = m;
       int k1 = m ,k2 = m;
       do
       {
           k1 = next(n ,k1);if(Ans < k1) Ans = k1;
           k2 = next(n ,k2);if(Ans < k2) Ans = k2;
           k2 = next(n ,k2);if(Ans < k2) Ans = k2;
       }while(k1 != k2);
       printf("%d " ,Ans);
   }
   return 0;
}




map判断是否出现过


#include<stdio.h>
#include<map>


using namespace std;


int mk[15];
map<int ,int>mark;


void inint()
{
     mk[0] = 1;
     for(int i = 1 ;i <= 9 ;i ++)
     mk[i] = mk[i-1] * 10;
}


long long next(int n ,int a)
{
    long long now = (long long)a * (long long)a;
    while(now >= mk[n])
    now /= 10;
    return int(now);
}


int main ()
{
   int t ,n ,m ,Ans;
   inint();
   scanf("%d" ,&t);
   while(t--)
   {
       scanf("%d %d" ,&n ,&m);
       Ans = m;
       mark.clear();
       mark[m] = 1;
       while(1)
       {
          m = next(n ,m);
          if(Ans < m) Ans = m;
          if(mark[m]) break;
          mark[m] = 1;
       }
       printf("%d " ,Ans);
   }
   return 0;
}
            












            



原文地址:https://www.cnblogs.com/csnd/p/12062544.html