题目链接:http://codeforces.com/problemset/problem/382/C
题目意思:给定一个序列,问是否可以通过只插入一个数来使得整个序列成为等差数列,求出总共有多少可能的情况,并输出这些数。
n = 1 、 n = 2 和 整个序列是常数列 的情况比较容易判断。不过要注意n = 2的时候,也需要判断两个数之间是否也可以通过插入一个数来构成等差数列。
关键是讨论n>=3的情况。预处理:把整个输入序列从小到大排序。之后,得到公差是第一要务!如果可以从中插入一个数(这时一定不是两端,也就是说这两种情况是互斥的),那么两个相邻的数之差 = 公差的次数会是最多的!只要找到这个差出现不少于2次以上,这个差就是公差。
确定公差之后,后面的情况就比较容易判断。插入该数的两个相邻数之间的差不可能等于公差,而该数是否合法,可以通过这两个相邻数中较小的一个 + 2倍公差,能否得到较大的数来判断。
如果插入的数不在中间,那么有可能是无解(输出0,插入哪个位置都不能使得序列成为等差数列)或者是从两端插入(输入的序列已经是等差数列)
还有一种情况要特别注意,当序列只有3个数的时候,并且可以从中插入一个数成为等差数列的情况。此时公差取较小的那个差,因为较大的差之间比较小的差能插入该数的可能性更大。例如序列:1 3 4,我们会取1作为公差,而不是2,此时可在1和3之间插入2来构成等差数列。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <algorithm> 5 using namespace std; 6 7 const int maxn = 1e5 + 5; 8 int a[maxn]; 9 10 int main() 11 { 12 int i, cnt, n, d, ans, td, td1, c1, c2; 13 while (scanf("%d", &n) != EOF) 14 { 15 for (i = 1; i <= n; i++) 16 scanf("%d", &a[i]); 17 sort(a+1, a+n+1); 18 d = a[2]-a[1]; 19 if (n == 1) // 可以插入无限个数,只要等于a[1]就行 20 printf("-1 "); 21 else if (a[1] == a[n] && n >= 2) // 常数列 22 printf("1 %d ", a[1]); 23 else if (n == 2) 24 { 25 if ((a[1] + a[2]) % 2) // 判断相邻数之间是否也可以插入 26 printf("2 %d %d ", a[1]-d, a[2]+d); 27 else 28 printf("3 %d %d %d ", a[1]-d, (a[1]+a[2])/2, a[2]+d); 29 } 30 else 31 { 32 if (n >= 3) 33 { 34 c2 = c1 = 1; 35 td1 = a[3]-a[2]; 36 if (td1 != d) 37 { 38 for (i = 4; i <= n; i++) 39 { 40 int td = a[i] - a[i-1]; 41 // 出现次数>=2的差即为整个序列的公差 if (td == td1) 42 c2++; 43 else 44 c1++; 45 if (c1 >= 2 || c2 >= 2) 46 break; 47 } 48 } 49 if (c2 >= c1 && n >= 3 && d > td1) // 最终确定公差 50 d = td1; 51 } 52 cnt = 0; 53 for (i = 2; i <= n; i++) 54 { 55 td = a[i] - a[i-1]; 56 if (d != td) 57 { 58 cnt++; 59 if ((a[i-1]+a[i]) % 2 || a[i-1]+2*d != a[i]) 60 { 61 cnt++; 62 break; 63 } 64 else 65 ans = a[i-1] + d; 66 } 67 } 68 if (!cnt) 69 printf("2 %d %d ", a[1]-d, a[n]+d); 70 else if (cnt == 1) 71 printf("1 %d ", ans); 72 else 73 printf("0 "); 74 } 75 } 76 return 0; 77 }