#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int a[15];
int n,k,t;
set<int> s;
int cal(int k)
{
int len=0,ans=0;
LL kk=(long long)k*k;
while(kk>0)
{
a[len++]=kk%10;
kk/=10;
}
//cout<<len<<endl;
int l=min(n,len);
for(int i=0;i<l;i++)
{
len--;
// cout<<"flag "<<a[len]<<endl;
ans=ans*10+a[len];
}
// cout<<ans<<endl;
return ans;
}
void solve()
{
int ans=k,x=k;
s.insert(k);
while(1)
{
x=cal(x);
//cout<<x<<endl;
ans=max(ans,x);
if(!s.count(x)) s.insert(x);
else break;
}
printf("%d\n",ans);
}
int main()
{
scanf("%d",&t);
while(t--)
{
s.clear();
scanf("%d%d",&n,&k);
solve();
}
return 0;
}
题目地址:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2544
题解:计算器显示的数一定会出现循环,每次判断得到的数是否以前出现过,并更新最大值即可。
Floyd判圈:
假设有两个小孩子在一个可以无限向前跑的跑道上赛跑,同时出发,但其中一个小孩的速度是另一个的两倍,如果跑道是直的,跑得快的小孩永远在前面;但如果有环,则跑得快的小孩将追上跑得慢的小孩。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int a[15];
int n,k,t;
int cal(int k)
{
int len=0,ans=0;
LL kk=(long long)k*k;
while(kk>0)
{
a[len++]=kk%10;
kk/=10;
}
int l=min(n,len);
for(int i=0; i<l; i++)
{
len--;
ans=ans*10+a[len];
}
return ans;
}
void solve()
{
int ans=k,k1=k,k2=k;
do
{
k1=cal(k1);
ans=max(k1,ans);
k2=cal(k2);
ans=max(ans,k2);
k2=cal(k2);
ans=max(ans,k2);
}while(k1!=k2);
printf("%d\n",ans);
}
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&k);
solve();
}
return 0;
}