例题1.19 计算器谜题 UVa11549

1.题目描述:点击打开链接

2.解题思路:本题是一道普通的模拟题,根据题意易知计算器显示的数将会出现循环,因为显示的n位数一共就有限种情况,而平方的次数是无限多的。所以不妨一个个的模拟,每次都看新得到的数是否以前出现过,如果出现过就跳出循环。但如何判断是否出现过呢?第一种方法是利用STL中的set,同时写一个Next函数求出下一个k值。下面一共给出三个不同的代码,来分别体会一下效率上的巨大差异。

3.代码:

(一,Next函数中使用string,stringstream)

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<string>
#include<sstream>
#include<set>
#include<vector>
#include<stack>
#include<map>
#include<queue>
#include<deque>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<functional>
using namespace std;

typedef long long LL;
int Next(int n, int k)
{
	stringstream ss;
	ss << (LL)k*k;//为了防止结果溢出,要转化为long long
	string s = ss.str();
	if (s.length() > n)s = s.substr(0, n);//结果太长,取前n位
	int ans;
	stringstream ss2(s);
	ss2 >> ans;
	return ans;
}
int main()
{
	//freopen("t.txt", "r", stdin);
	int T;
	cin >> T;
	while (T--)
	{
		int n, k;
		cin >> n >> k;
		set<int>s;
		int ans = k;
		while (!s.count(k))//以前没有出现过
		{
			s.insert(k);
			if (k > ans)ans = k;
			k = Next(n, k);
		}
		cout << ans << endl;
	}
	return 0;
}

提交后OJ显示的结果如下:

(二,Next函数中把string,stringstream换位普通的char数组)

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<string>
#include<sstream>
#include<set>
#include<vector>
#include<stack>
#include<map>
#include<queue>
#include<deque>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<functional>
using namespace std;

typedef long long LL;
int buf[100];
int Next(int n, int k)
{
	if (!k)return 0;
	LL k2 = (LL)k*k;
	int L = 0;
	while (k2 > 0)
	{
		buf[L++] = k2 % 10;//低位在前,高位在后
		k2 /= 10;
	}
	n = min(n, L);//取较小者
	int ans = 0;
	for (int i = 0; i < n; i++)
		ans = ans * 10 + buf[--L];
	return ans;
}
int main()
{
	//freopen("t.txt", "r", stdin);
	int T;
	cin >> T;
	while (T--)
	{
		int n, k;
		cin >> n >> k;
		set<int>s;
		int ans = k;
		while (!s.count(k))
		{
			s.insert(k);
			if (k > ans)ans = k;
			k = Next(n, k);
		}
		cout << ans << endl;
	}
	return 0;
}

提交后OJ显示的结果如下:

(三,利用Floyed判圈算法)

(1)概述:该算法的原理很简单,如果A,B两个人赛跑,B的速度是A的两倍,那么当跑道是直线时,肯定B永远在A的前面;当跑到是圆形时,则B将慢慢地追上A,这便是Floyed判圈算法。

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<string>
#include<sstream>
#include<set>
#include<vector>
#include<stack>
#include<map>
#include<queue>
#include<deque>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<functional>
using namespace std;

typedef long long LL;
int buf[100];
int Next(int n, int k)
{
	if (!k)return 0;
	LL k2 = (LL)k*k;
	int L = 0;
	while (k2 > 0)
	{
		buf[L++] = k2 % 10;//低位在前,高位在后
		k2 /= 10;
	}
	n = min(n, L);
	int ans = 0;
	for (int i = 0; i < n; i++)
		ans = ans * 10 + buf[--L];
	return ans;
}
int main()
{
	//freopen("t.txt", "r", stdin);
	int T;
	cin >> T;
	while (T--)
	{
		int n, k;
		cin >> n >> k;
		set<int>s;
		int ans = k;
		int k1 = k, k2 = k;
		do
		{
			k1 = Next(n, k1);//小孩A
			k2 = Next(n, k2); if (k2 > ans)ans = k2;
			k2 = Next(n, k2); if (k2 > ans)ans = k2;//小孩B,速度是A的两倍
		} while (k1 != k2);//追上后停止
		cout << ans << endl;
	}
	return 0;
}



时间: 2024-07-31 18:28:06

例题1.19 计算器谜题 UVa11549的相关文章

UVA11549 Calculator Conundrum 计算器谜题

就觉得这题的暴力解法时间复杂度应该会很高,可能循环节会比较小吧 比较好的收获就是这个Floyd判环法 #include <set> #include <cstdio> #include <iostream> #include <algorithm> using namespace std; typedef long long LL; const int maxn = 100005; const int INF = 0x3f3f3f3f; LL pow10 (

UVa 11549 计算器谜题(Floyd判圈算法)

https://vjudge.net/problem/UVA-11549 题意: 有一个老式计算器,只能显示n位数字,输入一个整数k,然后反复平方,如果溢出的话,计算器会显示结果的最高n位.如果一直这样做下去,能得到的最大数是多少? 思路: 这个肯定是会循环的. 比较普通的做法就是用set来判断是否出现过来终止循环. 另一个高效算法:Floyd判圈算法!! 想象一下,假设有两个小孩子在一个“可以无限向前跑”的跑道上赛跑,同时出发,但其中一个孩子的速度是另一个两倍.如果跑到是直的,跑得快的小孩永远

uva 11549计算器谜题(floyd判圈算法)

 题意:有个老式计算器,每次只能记住一个数字的前n位.现在输入一个整数k,然后反复平方,一直做下去,能得到的最大数是多少.例如,n=1,k=6,那么一次显示:6,3,9,1... 思路:这个题一定会出现循环,所以一个个模拟,遇到相同的就再之前所有数中找最大的输出即可. 最容易想到的就是set判重,一开始k直接生算每次除十......超时 然后看了书,用string,ac,很方便但是时间达到了4s,果然string和stringstream好慢啊......... 又改成了记录k*k的每一位,

例题3.19 优势人群 UVa11020

1.题目描述:点击打开链接 2.解题思路:本题利用multiset解决.根据题意,如果我们用P(x,y)表示一个人,因为人可以相同,所以用multiset.我们会发现,如果所有人群都是有优势的,那么这些点呈现一个递减的趋势.如果刚刚插入一个人,他是否有优势该如何判断呢?只需要看他左边相邻的点的y坐标是否比他小即可.而如果这个人是有优势的,那么需要先把这个人插入到集合中,然后从upper_bound(P)开始,逐个删除没有优势的点,注意删除时候应写为s.erase(it++),因为删除时候会导致指

一个比较好的Java写的计算器代码 (转)

1 import java.awt.BorderLayout; 2 import java.awt.Color; 3 import java.awt.GridLayout; 4 import java.awt.event.ActionEvent; 5 import java.awt.event.ActionListener; 6 7 import javax.swing.JButton; 8 import javax.swing.JFrame; 9 import javax.swing.JPan

c#基础 1,100以内的与7相关的数字;2,计算器,3,判断是不是一个正整数,4,判断体重

//输出语句   Console.ReadLine();           //输入语句    Console.WriteLine();            /// 给函数加注解:            /**/  //一段区域           // 数据类型            //  1,整型 int:            //  2,浮点型 double:            //  3,字符串型 string;            //  4,布尔型 bool (1)tr

java经典题目

/***********Ryear.java begin********************/ import java.util.Scanner;public class Ryear { /** * @param args */ public static void main(String[] args) { /** * 编写程序,判断给定的某个年份是否是闰年. * 闰年的判断规则如下: * (1)若某个年份能被4整除但不能被100整除,则是闰年. * (2)若某个年份能被400整除,则也是

窗体==&gt;&gt;初始Windows程序

初识Windows程序 01.创建Windows程序(VS) 01.打开Visual Studio开发工具 02.选择"文件"→"新建"→"项目" 命令. 03.项目类型选择"Visual C#". 04.模板选择"Windows窗体应用程序". 05."起名"→"确认". 02.认识Windows程序 01.Form1.cs:窗口文件,程序员对窗体编写的代码一般都会

java学习资料

必须养成好的的编码习惯:缩进(用空格).注释.命名约定. 大小写敏感. 单独的":"代表一条空语句. main函数是我们整个程序的执行入口所以必须是静态公开的. 必须写成这样:  public static void main(String[]args){...} 生成jar包: 在eclipse里,选中要打包的几个文件,右键-Export-写文件名-Next-Next-选main方法的class-finish 在jar包的同一文件夹下,新建一个空文档,写"java -jar