【UVALive 11549】

题目链接: http://acm.hust.edu.cn:8080/judge/problem/viewProblem.action?id=28547

题目大意:  给你两个整数n,k,让k不停平方,每次平方完取出前n位数,让你找到最大的前n位数。

解题思路:    自己列几项就可以看出一定是一个循环。当发现有重复的出现时循环就结束。

                  本题解法好多。

解法1,用sstream流和set函数,4494ms。

View Code
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <set>
 4 #include <cstring>
 5 #include <algorithm>
 6 #include <sstream>
 7 using namespace std;
 8 
 9 int next(int n, int k)
10 {
11     stringstream ss;  /// streamstring通常用来做数据转换的,可将int,char,long long, double 和string相互转换
12     ss << (long long)k*k;  /// 向ss中插入k*k
13     string s=ss.str();    /// 拷贝流缓冲到一个string对象s中
14     if(s.length()>n)  s=s.substr(0,n);
15     stringstream ss2(s);  ///再将s转换成流ss2
16     int ans;
17     ss2 >> ans;  ///抽取ss2中的数据传递给ans,实现转换
18     return ans;
19 }
20 
21 int main()
22 {
23     int n, k, T;
24     cin >> T;
25     while(T--)
26     {
27         cin >> n >> k;
28         set<int>s;
29         int ans=k;
30         while(!s.count(k))
31         {
32             s.insert(k);
33             if(ans<k)  ans=k;
34             k=next(n,k);
35         }
36             printf("%d\n",ans);
37     }
38     return 0;
39 }

解法2,因为stream流耗费太多时间,改成数组存储,1140ms。

View Code
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <set>
 4 #include <cstring>
 5 #include <algorithm>
 6 #include <sstream>
 7 using namespace std;
 8 
 9 
10 int next(int n, int k)
11 {
12     if(!k) return 0;
13     int a[30], ans=0;
14     long long  t=(long long)k*k;
15     int num=0;
16     while(t)
17     {
18         a[num++]=t%10;
19         t/=10;
20     }
21     if(num<n) n=num;;
22     for(int i=num-1; i>=num-n; i--)
23     {
24         ans=ans*10+a[i];
25     }
26     return ans;
27 }
28 
29 
30 int main()
31 {
32     int n, k, T;
33     cin >> T;
34     while(T--)
35     {
36         cin >> n >> k;
37         set<int>s;
38         int ans=k;
39         while(!s.count(k))
40         {
41             s.insert(k);
42             if(ans<k)  ans=k;
43             k=next(n,k);
44         }
45         printf("%d\n",ans);
46     }
47     return 0;
48 }

解法3,刚刚已经提到了这是一个循环,我们可以假设两个小孩在这个循环跑到里跑,孩子2跑得快,孩子1跑得慢,当孩子2追上孩子1时循环结束。这就是floyd判圈算法,500ms。

View Code
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <set>
 4 #include <cstring>
 5 #include <algorithm>
 6 #include <sstream>
 7 using namespace std;
 8 
 9 
10 int next(int n, int k)
11 {
12     if(!k) return 0;
13     int a[30], ans=0;
14     long long  t=(long long)k*k;
15     int num=0;
16     while(t)
17     {
18         a[num++]=t%10;
19         t/=10;
20     }
21     if(num<n) n=num;;
22     for(int i=num-1; i>=num-n; i--)
23     {
24         ans=ans*10+a[i];
25     }
26     return ans;
27 }
28 
29 int main()
30 {
31     int n, k, T;
32     cin >> T;
33     while(T--)
34     {
35         cin >> n >> k;
36         int k1= k, k2=k, ans=k;
37         do
38         {
39                    k1=next(n,k1);
40                    k2=next(n,k2);  ans=max(ans,k2);
41                    k2=next(n,k2);  ans=max(ans,k2);
42                  }  
43                 while(k1!=k2);
44         printf("%d\n",ans);
45     }
46     return 0;
47 }
原文地址:https://www.cnblogs.com/kane0526/p/2805096.html