UVA 11549 Calculator Conundrum (Floyd判圈算法)

 

UVA 11549 Calculator Conundrum (Floyd判圈算法)

分类: 思路独特   230人阅读  评论(0)  收藏  举报
uva 优化 Floyd 算法

题意:有个老式计算器,每次只能记住一个数字的前n位。现在输入一个整数k,然后反复平方,一直做下去,能得到的最大数是多少。例如,n=1,k=6,那么一次显示:6,3,9,1...

思路:这个题一定会出现循环,所以一个个模拟,遇到相同的就再之前所有数中找最大的输出即可。

怎么判断遇到相同的呢?如果装在数组里一一比较显然很慢,如果用v[k]判断k是否出现过,k范围太大空间不够用。

第一种方法是使用STL里的set来判重。

[cpp]  view plain copy
  1. #include<cstdio>  
  2. #include<set>  
  3. using namespace std;  
  4. int T,n,k;  
  5. int next(int x)//寻找x的后继  
  6. {  
  7.     if(!k) return 0;  
  8.     int buf[20],i=0;  
  9.     long long t=(long long)x*x;  
  10.     while(t)  
  11.     {  
  12.         buf[i++]=t%10;  
  13.         t/=10;  
  14.     }  
  15.     int ans=0;  
  16.     for(int j=1;j<=min(n,i);++j) ans=ans*10+buf[i-j];  
  17.     return ans;  
  18. }  
  19. int main()  
  20. {  
  21.     scanf("%d",&T);  
  22.     while(T--)  
  23.     {  
  24.         scanf("%d%d",&n,&k);  
  25.         set<int> S;  
  26.         while(!S.count(k))  
  27.         {  
  28.             S.insert(k);  
  29.             k=next(k);  
  30.         }  
  31.         printf("%d\n",*(--S.end()));  
  32.     }  
  33.     return 0;  
  34. }  

这个方法还是不够快的,第二种方法是用神奇的Floyd判圈算法。

如果两个小孩在直线跑道上跑同时出发,第二个小孩的速度是第一个小孩的两倍,那第二个小孩永远在前面。但如果在环形跑道上的话,第二个小孩将会“追上”第一个小孩。

[cpp]  view plain copy
  1. #include<cstdio>  
  2. #include<set>  
  3. using namespace std;  
  4. int T,n,k;  
  5. int next(int x)  
  6. {  
  7.     if(!k) return 0;  
  8.     int buf[20],i=0;  
  9.     long long t=(long long)x*x;  
  10.     while(t)  
  11.     {  
  12.         buf[i++]=t%10;  
  13.         t/=10;  
  14.     }  
  15.     int ans=0;  
  16.     for(int j=1;j<=min(n,i);++j) ans=ans*10+buf[i-j];  
  17.     return ans;  
  18. }  
  19. int main()  
  20. {  
  21.     freopen("in.txt","r",stdin);  
  22.     scanf("%d",&T);  
  23.     while(T--)  
  24.     {  
  25.         scanf("%d%d",&n,&k);  
  26.         int ans=max(k,next(k)),k1=k,k2=next(k);//k1是第一个小孩,k2是第二个小孩  
  27.         while(k1!=k2)  
  28.         {  
  29.             k1=next(k1);  
  30.             k2=next(k2); if(k2>ans) ans=k2; //小孩跑第一次  
  31.             k2=next(k2); if(k2>ans) ans=k2; //小孩跑第二次  
  32.         }  
  33.         printf("%d\n",ans);  
  34.     }  
  35.     return 0;  
  36. }  

你可能感兴趣的:(思路独特)