• 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 }

       

  • 相关阅读:
    【模板】辗转相除法
    【模板】冰茶姬(大概是全的?)
    【模板】快速幂
    【模板】线段树-区间修改
    【模板】线段树-单点修改,区间查询
    【模板】dijkstra与floyd
    【模板】SPFA(不完全详解)
    【济南集训】随机分数
    P3205 [HNOI2010]合唱队
    最大子列2
  • 原文地址:https://www.cnblogs.com/windysai/p/3525861.html
Copyright © 2020-2023  润新知