题目来源:http://poj.org/problem?id=1044
题目大意:
与众所周知的”千年虫“类似,某些计算机上存在日期记录的bug。它们的时钟有一个年份周期,每当到达最大值时,就会自动跳回到最小值。现给定一组这样的时钟,给出它们显示的年份y[i],周期的起始年份a[i],周期的结束年份b[i],求可能的真实年份的最小值。真实年份应该比所有的a[i]都大。
输入:多个测试用例组成,第一行为时钟数n,接下来的n行每行为一个时钟的信息,含三个整数y[i],a[i],b[i].含义见上面的描述。n为0时表示输入结束。
输出:输出计算得的真实年份,若找不到小于10000的真实年份,输出信息:"Unkown bugs detected.",用空格隔开每个用例的输出。格式见sample。
Sample Input
2 1941 1900 2000 2005 1904 2040 2 1998 1900 2000 1999 1900 2000 0
Sample Output
Case #1: The actual year is 2141. Case #2: Unknown bugs detected.
这题与前面的一些题目相比简单太多了。记b[i]-a[i]为t[i]表示每个时钟的周期,那么真实年份可以设为y[i] + k[i] * t[i];一开始我打算先求所有周期的最小公倍数限制试探k的范围,后来发现限制了真实年份最大值才10000,很可能比最小公倍数小很多,而且公倍数还很有可能发生溢出等情况,所以还不如直接以它作为限制界限。以y[0] + k * t[0]为真实年份的试探值,假设为Y,那么对于其他的时钟都应该满足Y=y[i] + k[i] * t[i],其中k[i]为非负整数。所以只要Y - y[i] >= 0 且 Y - y[i] 可以被t[i]整除,那么这个真实年份的试探值对于第i个时钟就是可行的。所以,从0开始试探每个k,直到找到对所有时钟都可行的Y或者Y超过10000时停止即可。
1 ////////////////////////////////////////////////////////////////////////// 2 // POJ1044 Date bugs 3 // Memory: 264K Time: 0MS 4 // Language: C++ Result: Accepted 5 ////////////////////////////////////////////////////////////////////////// 6 7 #include <iostream> 8 9 using namespace std; 10 11 int n; 12 int y[20]; 13 int a[20]; 14 int t[20]; 15 16 int main (void) { 17 int case_id = 0; 18 while (true) { 19 cin >> n; 20 if (n == 0) break; 21 for (int i = 0; i < n; ++i) { 22 cin >> y[i] >> a[i] >> t[i]; 23 t[i] -= a[i]; //计算出周期即可,b[i]以后不会再用到 24 } 25 int k = 0; 26 //依次检验每个k是否可行 27 while ((a[0] = y[0] + k * t[0]) < 10000) { 28 bool flag = true; 29 for (int i = 1; i < n; ++i) { 30 int p = a[0] - y[i]; 31 if (p < 0 || p % t[i] != 0) { 32 flag = false; 33 break; 34 } 35 } 36 if (flag) { 37 cout << "Case #" << ++case_id <<":" << endl; 38 cout << "The actual year is " << a[0] << "." << endl << endl; 39 break; 40 } 41 ++k; 42 } 43 if (a[0] >= 10000) { 44 cout << "Case #" << ++case_id <<":" << endl; 45 cout << "Unknown bugs detected." << endl << endl; 46 } 47 } 48 system("pause"); 49 return 0; 50 }