本题把握两点:
1. 按本题计算下去肯定是一个循环的过程。因为显示的位数是的,所有下一次的输入值在给定整数区间内。两种情况,计算某一输入值后与之前计算过的值重叠,得循环。第 二 种情况,或者说是极端情况,一直未遇到重复的数字,则最终区间内所有的数都已经被访问一次,接下来的输入值一定是区间内的值,得循环。综上最终一定会有循环。
2. 第二点是优化,有关于Floyd判圈法。因为最终一定是循环,则只要选取非循环部分和循环部分中的最大值,即可。如果按一般方法,保存所有中间值,如果当前值在之前已经出现过则出现环,种植,但这种方法复杂度为O(n^2)。如果只需要判断是否存在环,只需要按照Floyd判圈法,其复杂度为O(n)。两个人围田径场跑,一个人是另一个人的两倍速度,则最终两人一定会在起点相遇,如果相遇则一定出现了环,否则两倍速度的一定一直领先。
这里关于Floyd判圈法还有一点要注意,如果要记录所有路径过程中的节点,一定只能按照一倍速度访问的节点!
#include <cstdlib>
#include <iostream>
#include <stdio.h>
using namespace std;
long long m;
long long for_ward(int n,long long k,int step)
{
long long pos = k;
long len = 1;
for(int i = 1; i < n; i++)len *= 10;
for(int i = 0; i < step; i++)
{
pos *= pos;
long j = 10;
while(pos/len >= 10)
{
pos /= 10;
}
if(pos > m)m = pos;
}
return pos;
}
void caculate(long n, long k)
{
long long one,two;
one = two = k;
m = k;
do
{
one = for_ward(n,one,1);//m = max(m, one);
two = for_ward(n,two,2);//m = max(m, two);
}while(one != two);
printf("%lld\n",m);
}
int main(int argc, char *argv[])
{
long t,n,k;
scanf("%ld",&t);
while(t--)
{
scanf("%ld%ld",&n, &k);
caculate(n,k);
}
//system("PAUSE");
return 0;
}