例题10-2 不爽的 裁判( Disgruntled Judge, NWERC 2008, UVa12169)
有个裁判出的题太难, 总是没人做, 所以他很不爽。 有一次他终于忍不住了 , 心
想: “反正我的题没人做, 我干嘛要费那么多心思出题? 不如就输入一个随机数, 输出一个
随机数吧。 ”
于是他找了 3个整数x1、 a和b, 然后按照递推公式xi=(axi-1+b) mod
10001计算出了 一个长
度为 2T的数列, 其中 T是测试数据的组数。
然后, 他把T和x1, x3, … , x2T-1写到输入文件中, x2,
x4,…, x2T写到了 输出文件中。
你的任务就是解决这个疯狂的题目 : 输入T, x1, x3, … , x2T-1, 输出 x2, x4, … , x2T。 输入保
证T≤100, 且输入的所有x值为 0~ 10000的整数。
如果有多种可能的输出, 任意输出一个即可。
分析
如果知道了 a, 就可以计算出 x2, 进而根据x3=(ax2+b) mod 10001算出 b。 有了 x1、 a和b,
就可以在O(T)时间内计算出整个序列了 。 如果在计算过程中发现和输入矛盾, 则这个a是非
法的。 由于a是0~ 10000的整数( 因为递推公式对10001取模) , 即使枚举所有的a, 时间效
率也足够高。
代码
1 #include<iostream> 2 using namespace std; 3 4 const int maxn = 100*2 + 5; 5 const int M = 10001; 6 int T, x[maxn]; 7 8 void solve() { 9 ///枚举a,b 10 for(int a = 0; a < M; a++) 11 for(int b = 0; b < M; b++) { 12 bool ok = true; 13 /** 14 根据当前的a,b 计算X(2T) 15 由X(2T-1)判断用当前a,b算得的X(2T)是否正确 16 正确,退出solve() 17 错误,继续枚举a,b 18 */ 19 for(int i = 2; i <= T*2; i += 2) { 20 x[i] = (a*x[i-1] + b) % M; 21 if(i+1 <= T*2 && x[i+1] != (a*x[i] + b) % M) { ok = false; break; } 22 } 23 if(ok) return; 24 } 25 } 26 27 int main () { 28 while(cin >> T) { 29 for(int i = 1; i <= T*2-1; i += 2) cin >> x[i]; 30 solve(); 31 for(int i = 2; i <= T*2; i += 2) cout << x[i] << " "; 32 } 33 return 0; 34 }