题目大意
用一个老式计算器,只显示n位数字,输入一个整数k后计算,计算器会反复平方,直至溢出,每次溢出只显示最高的n位,计算器会一直平方下去,直到出现重复的数字
分析
题目中已经暗示了计算器显示的数会出现循环,不妨一个一个的模拟,直至出现重复的数字,我们使用集合把出现过的数字进行记录。
上代码
#include<iostream>
#include<algorithm>
#include<set>
#include<string>
#include<sstream>
#define maxn 1000000+10
using namespace std;
int n, k;
set<int>se;
int cal(int n, int k) //计算后取k位;
{
stringstream ss;
ss << (long long)k*k;
string s = ss.str();
if (s.length() > n) //与谁比较!!!!!!
s = s.substr(0,n);
//cout << s << endl;;
stringstream ss2(s);
int ans;
ss2 >> ans;
return ans;
}
int main()
{
int T;
cin >> T;
while (T--)
{
cin >> n >> k;
ans = k;
while (!se.count(k)) //以前没有出现过;
{
//cout << k << endl;
se.insert(k);
k =cal(n, k);
if (k > ans) ans = k;
}
cout<<ans<<endl;
}
return 0;
}
这个算法运行时会异常慢,主要数字符的输入输出流,我们尝试优化 因为字符串的输入流满我们将其替换。因为计算的数不可能超过100位,我们定义一个100位的数组就足够了,当然为了保险起见,也可以将数组开大。
int self_cal(int n, int k)
{
int a[100];
long long kk = k * k;
int len = 0;
int i = 1;
if (!k) return 0;
while (kk > 0)
{
a[len++] = kk % 10;
kk /= 10;
}
if (n > len) n = len;
int ans = 0;
for (int i = 0; i < n; i++)
{
ans = ans * 10 + a[--len];
}
return ans;
}
这样的话运行时间就会降低了,还有一种方法可以降到更低,那就是Floyd判圈法,想象一下如果两个孩子赛跑,如果是直线跑道,速度慢的孩子和速度快的孩子永远不可能相遇,但如果时第二种情况,就迟早能相遇。
int ans = k;
int k2 = k,k1=k;
do { //floyd套圈法;
k1 = cal(n,k1);
k2 = cal(n, k2); if (k2 > ans) ans = k2; //cout << k2<<endl;
k2 = cal(n, k2); if (k2 > ans)ans = k2; //cout << k2<<endl;
} while (k2 != k1);
cout << ans << endl;