博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【set&&sstream||floyed判环算法】【UVa 11549】Calculator Conundrum
阅读量:5877 次
发布时间:2019-06-19

本文共 4843 字,大约阅读时间需要 16 分钟。

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 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 (1 ≤ ≤ 200), the number of test cases. Each test case contains two integers (1 ≤ ≤ 9) and (0 ≤ < 10n) where n is the number of digits this calculator can display 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

21 62 99
OUTPUT
999

Calgary Collegiate Programming Contest 2008

题解就不写了得意刘汝佳老师写的更深入浅出

题目已经暗示了计算器显示出的数将出现循环(想一想,为什么),所以不妨一个一个地模拟,每次判断新得到的数是否以前出现过。如何判断呢?一种方法是把所有计算出来的数放到一个数组里,然后一一进行比较。不难发现,这样每次判断需要花费非常多的时间,相当慢。能否开一个数组vis,直接读vis[k]判断整数k是否出现过呢?很遗憾,k的范围太大,开不下。在这种情况下,一个简便的方法是利用STL的集合,代码如下。

#include 
#include
#include
#include
#include
#include
#include
#include
#include
#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
s; int ans=k; while(!s.count(k)) { s.insert(k); if(k>ans) ans=k; k=next(n,k); } cout <
<
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 
#include
#include
#include
#include
#include
#include
#include
#include
#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
s; int ans=k; while(!s.count(k)) { s.insert(k); if(k>ans) ans=k; k=next(n,k); } cout <
<

上述程序的运行时间降为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 
#include
#include
#include
#include
#include
#include
#include
#include
#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 <
<

转载于:https://www.cnblogs.com/zy691357966/p/5480455.html

你可能感兴趣的文章
U盘启动盘制作工具箱 v1.0
查看>>
增强myEclipse的提示功能
查看>>
Zabbix汉化方法
查看>>
Java I/O系统基础知识
查看>>
Java多线程设计模式(2)生产者与消费者模式
查看>>
基于whoosh的flask全文搜索插件flask-msearch
查看>>
对象并不一定都是在堆上分配内存的
查看>>
刘宇凡:罗永浩的锤子情怀只能拿去喂狗
查看>>
php晚了8小时 PHP5中的时间相差8小时的解决办法
查看>>
JS(JavaScript)的初了解7(更新中···)
查看>>
svn文件管理器的使用
查看>>
Ansible playbook 使用
查看>>
for/foreach/linq执行效率测试
查看>>
js /jquery停止事件冒泡和阻止浏览器默认事件
查看>>
杭电1698--Just a Hook(线段树, 区间更新)
查看>>
长春理工大学第十四届程序设计竞赛(重现赛)I.Fate Grand Order
查看>>
好作品地址
查看>>
[翻译]Protocol Buffer 基础: C++
查看>>
runloop与线程的关系
查看>>
[Bzoj2246]迷宫探险(概率+DP)
查看>>