门票(hash表)

#10041. 「一本通 2.1 练习 7」门票
传统1000 ms512 MiB
862
通过
2992
提交
题目描述
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
数据范围与提示
30% 的数据 A, B, C \le { 10^5 };

100% 的数据 A, B, C \le { 10^9 }。

30% 的数据 空间限制 4\text{M}。(囿于测评系统的实现,这部分的空间限制取消)

#include<bits/stdc++.h>
using namespace std;
long long a,b,c,m=1;
const int M=1e9;
unordered_set<int> s;
int main()
{
	cin>>a>>b>>c;
	for(int i=1;;i++)
	{	
		if(i>2000000) {
			cout<<"-1";break;
		}
		if(s.count(m))
		{   cout<<i-1; 
			break;
		}
		s.emplace(m);
		m=(a*m+m%b)%c;
		
	}
	return 0;
}
#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;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值