【set&&sstream||floyed判环算法】【UVa 11549】Calculator Conundrum
CALCULATOR CONUNDRUM
Alice got a hold of an old calculator that can display n digits. She was bored enough to
come up with the following time waster.
She enters a number k then repeatedly squares it until the result
overflows. When the result overflows, only the n most significant digits are displayed on the screen and an error flag appears. Alice can clear the error and continue squaring the displayed number.
She got bored by this soon enough, but wondered:
“Given n and k, what is the largest number I can get by wasting time in this manner?”
Program
Input
The first line of the input contains an integer t (1 ≤ t ≤ 200), the number of
test cases. Each test case contains two integers n (1 ≤ n ≤ 9) and k (0 ≤ k < 10n) where n is the number of digits this calculator can display k is the starting number.
Program
Output
For each test case, print the maximum number that Alice can get by repeatedly squaring the starting
number as described.
Sample
Input & Output
INPUT
2
1 6
2 99
OUTPUT
9
99
Calgary Collegiate Programming Contest 2008
题解就不写了
刘汝佳老师写的更深入浅出
题目已经暗示了计算器显示出的数将出现循环(想一想,为什么),所以不妨一个一个地模拟,每次判断新得到的数是否以前出现过。如何判断呢?一种方法是把所有计算出来的数放到一个数组里,然后一一进行比较。不难发现,这样每次判断需要花费非常多的时间,相当慢。能否开一个数组vis,直接读vis[k]判断整数k是否出现过呢?很遗憾,k的范围太大,开不下。在这种情况下,一个简便的方法是利用STL的集合,代码如下。
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <ctime>
#include <algorithm>
#include <set>
#include <iostream>
#include <sstream>
#define uns unsigned
#define int64 long long
#ifdef WIN32
#define fmt64 "%I64d"
#else
#define fmt64 "%lld"
#endif
#define oo 0x13131313
#define REP(i, n) for (int i = 1; i <= (n); ++i)
#define FOR(start,end,n) for(int i=start,i <= (end);++i))
using namespace std; int next(int n,int k)
{
stringstream ss;
ss<<(int64)k*k;
string s=ss.str();
if(s.length()>n) s=s.substr(0,n);
int ans;
stringstream ss2(s);
ss2>>ans;
return ans;
} int main()
{
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;
}
set:
s.count(i)返还集合中i的次数
s.insert(k)将k插入
sstream
ss.str()可以返还存在流中的字符串
ss(s) ss赋初值
string
ss.substr 切断
还有几个成员函数记忆一下
sub.swap()//交换
sub.clear()
//清除
sub.size(),length()
sub.copy()
sub.c_str()
//将内容以C_string返回
sub.substr(a,b)
//返回某个子字符串(a到b)
上述程序在UVa OJ上的运行时间为4.5秒。有经验的读者应该知道,STL的string很慢,stringstream更慢,所以需要考虑把它们换掉。
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <ctime>
#include <algorithm>
#include <set>
#include <iostream>
#include <sstream>
#define uns unsigned
#define int64 long long
#ifdef WIN32
#define fmt64 "%I64d"
#else
#define fmt64 "%lld"
#endif
#define oo 0x13131313
#define REP(i, n) for (int i = 1; i <= (n); ++i)
#define FOR(start,end,n) for(int i=start,i <= (end);++i))
using namespace std;
int buf[30];
int next(int n,int k)
{
if(!k) return 0;
int tot=0,ans=0;
int64 temp;
temp=(long long)k*k;
while(temp>0)
{
buf[++tot]=temp%10;
temp=temp/10;
}
temp=1;
for(int i=tot-n+1;i<=tot;i++)
{
ans+=buf[i]*temp;
temp=temp*10;
}
return ans;
}
int main()
{
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;
}
上述程序的运行时间降为1秒。
当然,也可以用哈希表(详见《入门经典》的相关部分),但和set一样,空间开销比较大。有没有空间开销比较小且速度也不错的方法呢?答案是肯定的。
想象一下,假设有两个小孩子在一个“可以无限向前跑”的跑道上赛跑,同时出发,但其中一个小孩的速度是另一个的两倍。如果跑道是直的(如图1-25(a)所示),跑得快的小孩永远在前面;但如果跑道有环(如图1-25(b)所示),则跑得快的小孩将“追上”跑得慢的小孩。
图 1-25
这个算法称为Floyd判圈算法,不仅空间复杂度将降为O(1),运行时间也将缩短到0.5秒。主程序如下。
int main() {
int T;
cin>> T;
while(T--){
int n, k;
cin>> n >> k;
int ans =k;
int k1 =k, k2 = k;
do {
k1 =next(n, k1); //小孩1
k2 =next(n, k2); if(k2 > ans) ans = k2; //小孩2,第一步
k2 =next(n, k2); if(k2 > ans) ans = k2; //小孩2,第二步
}while(k1 != k2); //追上以后才停止
cout<< ans << endl;
}
return 0;
}
实际可能next 操作多了一倍 但是因为没用set所以反而更快了
省时间又省空间
最终的程序:
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <ctime>
#include <algorithm>
#include <set>
#include <iostream>
#include <sstream>
#define uns unsigned
#define int64 long long
#ifdef WIN32
#define fmt64 "%I64d"
#else
#define fmt64 "%lld"
#endif
#define oo 0x13131313
#define REP(i, n) for (int i = 1; i <= (n); ++i)
#define FOR(start,end,n) for(int i=start,i <= (end);++i))
using namespace std;
int buf[30];
int next(int n,int k)
{
if(!k) return 0;
int tot=0,ans=0;
int64 temp;
temp=(long long)k*k;
while(temp>0)
{
buf[++tot]=temp%10;
temp=temp/10;
}
temp=1;
for(int i=tot-n+1;i<=tot;i++)
{
ans+=buf[i]*temp;
temp=temp*10;
}
return ans;
}
int main()
{
int T;
cin>>T;
while(T--)
{
int n,k,k1,k2;
cin>>n>>k;
int ans=k;
k1=k;
k2=k;
do
{
k1=next(n,k1);
k2=next(n,k2);if(k2>ans) ans=k2;
k2=next(n,k2);if(k2>ans) ans=k2;
} while(k1!=k2);
cout <<ans<<endl;
}
return 0;
}
【set&&sstream||floyed判环算法】【UVa 11549】Calculator Conundrum的更多相关文章
- Floyd判圈算法 UVA 11549 - Calculator Conundrum
题意:给定一个数k,每次计算k的平方,然后截取最高的n位,然后不断重复这两个步骤,问这样可以得到的最大的数是多少? Floyd判圈算法:这个算法用在循环问题中,例如这个题目中,在不断重复中,一定有一个 ...
- UVA 11549 CALCULATOR CONUNDRUM(Floyd判圈算法)
CALCULATOR CONUNDRUM Alice got a hold of an old calculator that can display n digits. She was bore ...
- UVA 11549 Calculator Conundrum (Floyd判圈算法)
题意:有个老式计算器,每次只能记住一个数字的前n位.现在输入一个整数k,然后反复平方,一直做下去,能得到的最大数是多少.例如,n=1,k=6,那么一次显示:6,3,9,1... 思路:这个题一定会出现 ...
- 龟兔赛跑算法 floyed判环算法
今天写线段树写到要用到这个算法的题目,简单的学习一下. https://blog.csdn.net/javaisnotgood/article/details/89243876 https://blo ...
- Uva 11549 - Calculator Conundrum 找规律加map
题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...
- Floyed判环/龟兔算法
求[(5+2√6)2^x+1 ] mod p 的值,其中 0 ≤ x < 232 , p 是个质数,p ≤ 46337 .(这里介绍的是一种暴力的做法) (5+2√6)2^n+1 = an + ...
- floyd判环算法(龟兔赛跑算法)
floyd判环算法(龟兔赛跑算法) 注意,这个算法是用来判断一条链+一条环的图,环的长度或者环与链的交界处的,所以此floyd非彼floyd(虽然都是一个人想出来的). (图不是我的) 如果只要求环的 ...
- UVa 11549 计算器谜题(Floyd判圈算法)
https://vjudge.net/problem/UVA-11549 题意: 有一个老式计算器,只能显示n位数字,输入一个整数k,然后反复平方,如果溢出的话,计算器会显示结果的最高n位.如果一直这 ...
- hdu4975 A simple Gaussian elimination problem.(正确解法 最大流+删边判环)(Updated 2014-10-16)
这题标程是错的,网上很多题解也是错的. http://acm.hdu.edu.cn/showproblem.php?pid=4975 2014 Multi-University Training Co ...
随机推荐
- Global.asax使用2
ASP.NET中利用Application和Session统计在线人数.历史访问量 先来简单说一下ASP.NET中的Application和Session 下图是我们非常熟悉的Web应用程序的结构: ...
- Flex 扩展combobox 实现复选功能
前段时间,老大召唤,给个任务,研究一下flex的combobox控件 实现复选功能(flex自带的combobox控件不可以复选),小兵能力有限,哪里可以扩展呀,网上看了别人写的,发现总是有点瑕疵(关 ...
- 0118——RTLabel和正则表达式
RTLabel和RegexKitLite都要导入第三方库 使用Regexkitlite库进行正则表达式的解析 1.库是使用MRR,如果在ARC工程里面使用这个类,必须在project->buil ...
- 没有暑假的Ada 要好好努力咯 C#继续
- linux下python3连接mysql数据库
python语言的3.x完全不向前兼容,导致我们在python2.x中可以正常使用的库,到了python3就用不了了.比如说mysqldb 1.安装pymysql pymysql就是作为python3 ...
- HTML5 canvas 在线画笔绘图工具(一)
HTML5 canvas 在线画笔绘图工具(一) 功能介绍 这是我用Javascript写的第一个程序,在写的过程中走了很多弯路,所以写完之后想分享出来,给与我一样的初学者做为学习的参考,同时在编写这 ...
- css样式书写顺序
这里推荐先写显示属性,再写自身属性,再写文字属性:并不代表非得按这个顺序写,但这种写法可以使css结构更清晰易读,修改起来比较方便. 而且在团队项目中能更好地提高效率. //显示属性 display ...
- ubuntu 新建zend framework 项目
1. sudo apt-get install zend-framework /usr/share/php/libzend-framework-php 2. 配置include_path /etc/p ...
- Python学习笔记一,输入输出
输出:用print()在括号中加上字符串,就可以向屏幕上输出指定的文字.比如输出'hello, world',用代码实现如下>>>print('hello,world') 也可以是多 ...
- 开心菜鸟系列学习笔记------javascript(4)
一.全局上下文中的变量对象: 1)全局对象(Global object) 是在进入任何执行上下文之前就已经创建了的对象:这个对象只存在一份,它的属性在程序中任何地方都可以访问,全局对象的 ...