codeforces C. Arithmetic Progression 解题报告

题目链接: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 }

   

原文地址:https://www.cnblogs.com/windysai/p/3525861.html