門票
時間限制: 1 Sec 內存限制: 128 MB
提交: 26 解決: 2
[提交] [狀態] [討論版] [命題人:admin]
題目描述
RPK要帶MSH去一個更加神祕的地方!
RPK帶着MSH穿過廣場,在第1618塊磚上按下了一個按鈕,在一面牆上隨即出現了一個把手。RPK握住把手,打開了一扇石質大門。他們穿過悠長而芬芳的小道,走到了一扇象徵時間的大門――“the gate of time”。
門上寫着一個關於時間的謎題“承諾:____年”,RPK思考了一會,從容地用手指寫下1萬,這時,門開始發出閃光,MSH感覺到自己的心跳都快停止了。
門開了,眼前是一座美麗的神祕花園!
正當RPK和MSH準備進入的時候,突然出現了一個看門的老大爺QL。
QL:“你們幹什麼你們,還沒買票呢!”
RPK突然想起來現金全拿去買蛋糕了,RPK很紳士的問:“能刷卡麼?我身上沒現金。”
QL:“沒錢?那你們不能進去!”
RPK(汗):“……”
QL:“等等,我這有道不會的數學題,你解了我就讓你們進去。”
(衆人:“……”)
有一個數列{an},a0=1,ai+1=(A*ai+ai mod B)mod C,要求這個數列第一次出現重複的項的標號。
這點小問題當然難不倒數學bug男RPK了,僅憑心算他就得到了結果。
輸入
一行3個數,分別表示A B C
輸出
輸出第一次出現重複項的位置,如果答案超過2000000 輸出-1
樣例輸入
2 2 9
樣例輸出
4
提示
30%的數據A B C≤105
100%的數據 A B C≤109
試過set暴力,結果跑到90000左右的數據就T了,求教大佬之後才知道是用哈希做,建哈希表,選個適合的質數取模哈希,再暴力跑即可
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2200000;
const int modd = 2181271;
int hashh[maxn];
struct z
{
int nextt,v;
}z[maxn];
bool countt(int tmp, int tmpp)
{
for (int i = hashh[tmpp]; i; i = z[i].nextt)
if (tmp == z[i].v)
return 1;
return 0;
}
int main()
{
// freopen("in.txt", "r", stdin);
int a,b,c;
scanf("%d%d%d", &a, &b, &c);
hashh[1] = z[1].v = 1;
int tmp = 1;
for (int i = 1; i <= 2000000; i++)
{
tmp = ((ll) a * tmp + tmp % b) % c;
int tmpp = tmp % modd;
if (countt(tmp, tmpp))
{
printf("%d\n", i);
return 0;
}
z[i + 1].v = tmp;
z[i + 1].nextt = hashh[tmpp];
hashh[tmpp] = i + 1;
}
puts("-1");
return 0;
}