UVa11549 Calculator Conundrum

本文介绍了使用Floyd判圈算法解决特定数学问题的过程。通过对比两种不同的实现方式,一种利用map判圈,另一种采用Floyd判圈算法,展示了如何在数值平方后截取特定位数形成新的数值,并寻找循环的最大值。

  【原题链接

  k太大,hash数组开不下,用了map判圈。

View Code 1000+ms
 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <map>
 4 using namespace std;
 5 
 6 typedef long long LL;
 7 
 8 LL cal(int n, LL &v, LL &ans)
 9 {
10     v = v * v;
11     int L = 0;
12     LL tmp = v;
13     while(tmp)
14     {
15         L ++;
16         tmp /= 10;
17     }
18     LL t = 1;
19     if(n < L)
20     {
21         for(int i = 0; i < L - n; i ++)
22             t *= 10;
23     }
24     v /= t;
25     if(v > ans) 
26         ans = v;
27     return v;
28 }
29 int main()
30 {
31     int t, n, k;
32     map<LL, int> mp;
33     LL ans, v;
34     scanf("%d", &t);
35     while(t --)
36     {
37         mp.clear();
38         scanf("%d%d", &n, &k);
39         v = ans = (LL)k;
40         while(mp[v] == 0)
41         {
42             mp[v] ++;
43             cal(n, v, ans);
44         }
45         printf("%lld\n", ans);
46     }
47     return 0;
48 }

 

  后来知道了“Floyd判圈算法”这么个东西。这个算法也比较形象的表达为“龟兔算法”,可以解决单链表成环问题。这个算法简要描述是这样的:

  乌龟每秒跑的距离是原来的一倍,兔子每秒跑的距离是原来的两倍,那么,如果在某个时刻,兔子追上乌龟并到达同一点,那么说明出现了圈(环)。可以结合下图看看:

  

      

  从上图可以看出,乌龟也是要跑的,这样才能确保乌龟也进入圈中。而由于兔子每秒跑是原来两倍的距离,减去乌龟的距离就得到圈周长(进而也可以求周期了)。

View Code 500+ms
 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <map>
 4 using namespace std;
 5 
 6 typedef long long LL;
 7 
 8 int buf[10];
 9 int next(int n, int k)
10 {
11     if(!k) return 0;
12     LL k2 = (LL)k * k;
13     int L = 0;
14     while(k2 > 0)
15     {
16         buf[L++] = k2 % 10;
17         k2 /= 10;
18     }
19     if(n > L)
20         n = L;
21     int ans = 0;
22     for(int i = 0; i < n; i ++)    
23         ans = ans * 10 + buf[--L];
24     return ans;
25 }
26 
27 int main()
28 {
29     int t, n, k;
30     scanf("%d", &t);
31     while(t --)
32     {
33         scanf("%d%d", &n, &k);
34         int ans = k;
35         int k1 = k, k2 = k;
36         do
37         {
38             k1 = next(n, k1);
39             k2 = next(n, k2); if(k2 > ans) ans = k2;
40             k2 = next(n, k2); if(k2 > ans) ans = k2;
41         }while(k1 != k2);
42         printf("%d\n", ans);
43     }
44     return 0;
45 }

转载于:https://www.cnblogs.com/huangfeihome/archive/2012/11/06/2757040.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值