题目描述
RPK 要带 MSH 去一个更加神秘的地方! RPK 带着 MSH 穿过广场,在第 1618
块砖上按下了一个按钮,在一面墙上随即出现了一个把手。RPK
握住把手,打开了一扇石质大门。他们穿过悠长而芬芳的小道,走到了一扇象征时间的大门——“the gate of time”。
门上写着一个关于时间的谜题 “承诺:____ 年”,RPK 思考了一会,从容地用手指写下 1 万,这时,门开始发出闪光,MSH
感觉到自己的心跳都快停止了。 门开了,眼前是一座美丽的神秘花园!正当 RPK 和 MSH 准备进入的时候,突然出现了一个看门的老大爷 QL。 QL:“你们干什么你们,还没买票呢!” RPK
突然想起来现金全拿去买蛋糕了,RPK 很绅士的问:“能刷卡么?我身上没现金。” QL:“没钱?那你们不能进去!” RPK(汗):“……”
QL:“等等,我这有道不会的数学题,你解了我就让你们进去。” (众人:“……”)
有一个数列 {a_n}, a_0 = 1, a_{i+1} = (A\times{a_i} + a_i \bmod B) \bmod C,要求这个数列第一次出现重复的项的标号。
这点小问题当然难不倒数学 bug 男 RPK 了,仅凭心算他就得到了结果。
输入格式
一行三个数,分别表示 A, B, C。
输出格式
输出第一次出现重复项的位置,如果答案超过 2\times 10^6 输出 -1。
样例
输入
2 2 9
输出
4
代码1(手打hash)
#include<bits/stdc++.h>
using namespace std;
long long A,B,C,tmp,i,num=1;
const int H=1900001;
int t[10000005];
int nxt[1000000],hed[H];
int h(long long a){
return a%H;
}
bool insert(int s,int way){
int v=h(t[s]);
int u=hed[v];
while (u){
if (t[u]==t[s]) return true;
u=nxt[u];
}
if (way==1) return false;
nxt[s]=hed[v];hed[v]=s;
return true;
}
int main(){
cin>>A>>B>>C;
t[1]=1;
for (i=2;;i++){
if (i>=2000000+1){printf("-1");break;}
if (insert(i-1,1)){cout<<i-1-1;break;}
insert(i-1,0);
num=(A*num+num%B)%C;t[i]=num;
}
return 0;
}
代码2(STL库)
#include<bits/stdc++.h>
using namespace std;
long long A,B,C,tmp,i,num=1;
unordered_set<long long> s;
int main(){
cin>>A>>B>>C;
for (i=1;;i++){
if (i>=2000000){printf("-1");break;}
if (s.count(num)==1){cout<<i-1;break;}
s.emplace(num);num=(A*num+num%B)%C;
}
return 0;
}
代码3(。。。)
#include<bits/stdc++.h>
using namespace std;
long long a,b,c,m=1;
const int M=1e9;bool q[M];
int main()
{
cin>>a>>b>>c;
for(int i=1;;i++)
{
if(i>2000000) {cout<<"-1";break;}
if(q[m]){cout<<i-1; break;}
q[m]=1;m=(a*m+m%b)%c;
}
return 0;
}
unordered_set
这里讲解第二种方法:
emplace
:在集合中插入一个新元素。该函数的参数是要插入的元素。count
:返回集合中特定元素的个数。由于unordered_set
中的元素是唯一的,所以该函数的返回值只能是0或1。
需要注意的是,此方法仅能在-o2下通过,但只要稍加修改便能成为第三种方法通过此题,细节留给读者思考