SGU 455 Sequence analysis

http://acm.sgu.ru/problem.php?contest=0&problem=455

  一道关于cycle detection技术的数论题。我用的是wiki中提到的第二种方法,跑出来的时间大约350ms。

  题目说了数的范围是有符号的长整形,开始的时候我考虑到数据可能溢出,于是我就用了模乘法,可是交的时候在第6或第7个test的就TLE了。TLE了以后我就直接删去了模乘法,不过因为开始的时候限制计算的次数的判断的位置放的不对,所以在某些数据上会TLE或者wa。比较幸运的是,我随便测了一组数据就发现问题了。改过来以后就AC了~

原始代码:

View Code
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <iostream>
 5 #include <algorithm>
 6 
 7 using namespace std;
 8 typedef long long ll;
 9 const int maxCnt = 2000000;
10 
11 ll A, B, C;
12 
13 ll multiMod(ll a, ll b, ll m) {
14     ll ret = 0;
15 
16     while (b) {
17         if (b & 1) {
18             ret += a;
19             ret %= m;
20         }
21         a <<= 1;
22         a %= m;
23         b >>= 1;
24     }
25 
26     return ret;
27 }
28 
29 ll cal(ll x) {
30     return (A * x + x % B) % C;
31 //    if (x >= 0) return (multiMod(A, x, C) + x % B) % C;
32 //    else if (A >= 0) return (multiMod(x, A, C) + x % B) % C;
33 //    else return (multiMod(-x, -A, C) + x % B) % C;
34 }
35 
36 ll brent(ll base, int &lam, int &mu) {
37     ll ep, slow, fast;
38 
39     ep = lam = 1;
40     slow = base;
41     fast = cal(base);
42     while (slow != fast) {
43         if (ep == lam) { // get into a new power of two
44             slow = fast;
45             ep <<= 1;
46             lam = 0;
47         }
48         fast = cal(fast);
49         lam += 1;
50         if (lam >= maxCnt) return -1;
51     }
52 //    cout << slow << " " << fast << endl;
53     // find the first repetition of lam
54     mu = 0;
55     slow = fast = base;
56     for (int i = 0; i < lam; i++) {
57         fast = cal(fast);
58     }
59 //    cout << "lam " << lam << endl;
60     while (fast != slow) {
61         slow = cal(slow);
62         fast = cal(fast);
63         mu++;
64     }
65 
66     if (mu + lam <= maxCnt) return mu + lam;
67     else return -1;
68 }
69 
70 int main() {
71 //    freopen("in", "r", stdin);
72 
73     while (cin >> A >> B >> C) {
74         int first, cycle;
75 
76         cout << brent(1, cycle, first) << endl;
77 //        cout << first << ' ' << cycle << endl;
78 //        cout << A << ' ' << B << ' ' << C << endl;
79 //        for (ll i = 0, k = 1; i <= cycle + first; i++) {
80 //            cout << k << ' ';
81 //            k = cal(k);
82 //        }
83 //        cout << endl << endl;
84     }
85 
86     return 0;
87 }

——written by Lyon

原文地址:https://www.cnblogs.com/LyonLys/p/sgu_455_Lyon.html