想了老半天,只会暴力,然后就过了。。
实现由三种方法,一是STL,而是哈希技术,三是Floyd判圈法。
就速度而言,Floyd判圈法>哈希技术>STL。分别跑了70ms,180ms,480ms。STL真是慢的可以。
就空间而言,Floyd判圈法<STL<哈希技术。
也就是说,STL与哈希技术在空间和时间上各有千秋,但Floyd判圈法完爆一切= =。
关于Floyd判圈法的一些理解。
Floyd判圈法不需要开任何储存空间。
时间上也不需要调用STL那么笨重的东西,也不需要像哈希技术那样循环检查。
可以理解为优化了空间,同时也就优化了时间。
本质是让他们都跑起来,而且一个比另一个快。都跑起来才能都进入圈里。一个比另一个快才可能相遇。
慢的速度取1,快的速度取2。每次更新花费时间最少,而且最多花一圈就能追上。
Floyd判圈法的代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
inline ll mp(ll x,ll n)
{
ll ret=1;
while(n)
{
if(n&1) ret*=x;
x*=x;
n>>=1;
}
return ret;
}
inline ll NEXT(ll x,ll r)
{
x*=x;
while(x>=r) x/=10;
return x;
}
int main()
{
ll t;
scanf("%lld",&t);
while(t--)
{
ll n,k;
scanf("%lld %lld",&n,&k);
ll k1=k;
ll k2=k;
ll ans=k;
ll r=mp(10,n);
do
{
k1=NEXT(k1,r);
k2=NEXT(k2,r);ans=max(ans,k2);
k2=NEXT(k2,r);ans=max(ans,k2);
}while(k1!=k2);
printf("%lld\n",ans);
}
return 0;
}
哈希技术的代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
inline ll mp(ll x,ll n)
{
ll ret=1;
while(n)
{
if(n&1) ret*=x;
x*=x;
n>>=1;
}
return ret;
}
inline ll NEXT(ll x,ll r)
{
x*=x;
while(x>=r) x/=10;
return x;
}
const ll hashsize=1000005;
const ll maxstate=1000005;
ll head[hashsize];
struct node
{
ll v,next;
}Node[maxstate];
ll tot;
inline void init()
{
tot=0;
memset(head,-1,sizeof(head));
}
inline ll add(ll s)
{
ll h=s%1000000;
for(ll i=head[h];i!=-1;i=Node[i].next)
if(Node[i].v==s) return 0;
Node[tot].v=s;
Node[tot].next=head[h];
head[h]=tot++;
return 1;
}
int main()
{
ll t;
scanf("%lld",&t);
while(t--)
{
ll n,k;
scanf("%lld %lld",&n,&k);
ll r=mp(10ll,n);
init();
ll MAX=k;
while(add(k))
{
k=NEXT(k,r);
MAX=max(MAX,k);
}
printf("%lld\n",MAX);
}
return 0;
}
STL的代码(编码十分简单)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,k;
set<ll>s;
ll mp(ll x,ll n)
{
ll ret=1;
while(n)
{
if(n&1) ret*=x;
x*=x;
n>>=1;
}
return ret;
}
int main()
{
ll t;
scanf("%lld",&t);
while(t--)
{
scanf("%lld %lld",&n,&k);
ll r=mp(10ll,n);
s.clear();
while(!s.count(k))
{
s.insert(k);
k*=k;
while(k>=r) k/=10;
}
printf("%lld\n",*(--s.end()));
}
return 0;
}