计算器谜题(判圈算法)

有一个老式计算器,只能显示n位数字。有一天,你无聊了,于是输入一个整数k,然后反复平方,直到溢出。每次溢出,计算器会显示出结果最高n位和一个错误标记。然后清除错误标记,继续平方。如果一直这样一直做下去,能得到的最大数是多少,比如当n=1,k=6时,计算器将依次显示6 , 3 (36的最高位),9,8(81的最高位),6(64的最高位),3…
输入格式
输入的第一行为一个整数T(1<=T<=200),即测量数据的数量,一下T行,每行保包含两个整数n和k(1<=n<=9,0<=k<=10n)。
输出格式
对于每组数据,输出你能得到的最大数。

#include<iostream>
#include<sstream>
#include<set>
using namespace std;
typedef long long LL;
int next(int n,int k)
{
	stringstream ss;
	ss<<(LL)k*k;
	string s=ss.str();
	if(s.length()>n)
	s=s.substr(0,n);
	stringstream ss1;
	int ans;
	ss1>>ans;
	return ans;
}
int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		int n;
		int k;
		scanf("%d%d",&n,&k);
		ans=k;
		set<int >s;
		while(s.count())
		{
			s.insert(k);
			if(k>ans) ans=k;
			k=next(n,k); 	
		}
		cout<<ans<<endl;
	}
	return 0;
}

上述程序的运行时间为4.5秒,STL的string很慢,而stringstream更慢,所以需要把他们换掉。

#include<iostream>
using namespace std;
typedef long long LL; 
int buf[10];
int next(int n,int k)
{
	if(!k) retue 0;
	int L=0;
	LL k2=(LL) k*k;
	while(k2)
	{
		buf[L++]=k%10;//分离并保存K^2^的各个数字
		K2/=10;
	}
	if(n>L)n=L;//不能让取得的位数超过数字背身已有的位数
	int ans=0;
	for(int i=0;i<n;i++)
		ans=ans*10+buf[--L];//把前面的n位重新的组合起来
	return ans;
}
int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		int n,k;
		cin>>n>>k;
		int ans=k;
		int k1=k;
		int k2=k;
		do{
			k1=next(n,k1);//小孩1
			k2=next(n,k2); if(k2>ans) ans=k2;//小孩二,第一步
			k2=next(n,k2); if(k2>ans) ans=k2;//小孩二,第一步
		}while(k1!=k2);//追上以后才停止
		cout<<ans<<endl;
	}
}

代码分析:
主函数中的K1,k2用到了Floyd判圈算法,想象一下,假设有两个孩子在一个"可以无限向前跑"的赛道上赛跑,同时出发,但其中,
一个孩子的数独是另一个孩子速度的两倍。如果跑到是直的那么跑得快的小孩将一直在前面,但是如果跑有环,则跑的快的小孩将"追上"跑的慢的小孩。正如我们在主函数中写的k1走了一步,k2走了两步。又因为取得整数是有环型分布趋势的所以k2会追上k1的。

在这里插入图片描述

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值