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