zoukankan      html  css  js  c++  java
  • CF刷题-Codeforces Round #481-D. Almost Arithmetic Progression

    题目链接:https://codeforces.com/contest/978/problem/D

    题解:

      题目的大意就是:这组序列能否组成等差数列?一旦构成等差数列,等差数列的公差必定确定,而且,对于给定的数列,公差的可能性是已知的。

      我的解决思路是:对于给定的数列,最后一位数 - 第一位数 / (n -1) 必定是公差,而对于我们要判断的原数列,其最后一位 - 第一位数的值是可以-2,-1,0,+1,+2的,穷举可能性一切公差,找出变动最小的情况。代码如下(有点小复杂,没优化):

      

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<map>
    #include<iostream>
    #include<vector>
    #include<string>
    #include<cmath>
    #include<set>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    const int N = 100000+5;
    int ini[N];
    int ans[N];
    int tofopr;
    set<int> jg;
    int isok(int n,int newc){
        int c = ans[1];
        int t = 0;
        for(int i = 2;i<=n - 1;i++){
            c+= newc;
            if(abs(ini[i] - c) > 1) return -1;
            if(ini[i] != c){
                t++;
            }
        }
        return t;
    }
    
    int main(void){
        int n;
        jg.clear();
        scanf("%d",&n);
        if(n <= 2){
            int b;
            for(int i = 1;i<=n;i++){
                scanf("%d",&b);
            }
            printf("0
    ");
        }
        else{
            int b;
            for(int i = 1;i<=n;i++){
                scanf("%d",&b);
                ini[i] = b;
            }
            int c = ini[n] - ini[1];
            int start,end;
            for(int i = c -2;i<=c+2;i++){
                tofopr = 0;
                if(i%(n-1) == 0){
                    int newc = i / (n - 1);
                    if(i == c - 2){
                        start = ini[1] + 1;
                        end = ini[n] - 1;
                        if(end >= 0){
                            ans[1] = start;
                            ans[n] = end;
                            tofopr = isok(n,newc);
                            if(tofopr >= 0){
                                tofopr += 2;
                                jg.insert(tofopr);
                            }
                        }
                    }
                    if(i == c -1){
                        start = ini[1];
                        end = ini[n] - 1;
                        if(end >= 0){
                            ans[1] = start;
                            ans[n] = end;
                            tofopr = isok(n,newc);
                            if(tofopr >= 0){
                                tofopr += 1;
                                jg.insert(tofopr);
                            }
                        }
                        start = ini[1] + 1;
                        end = ini[n];
                        ans[1] = start;
                        ans[n] = end;
                        tofopr = isok(n,newc);
                        if(tofopr >= 0){
                            tofopr += 1;
                            jg.insert(tofopr);
                        }
                    }
                    if(i == c){
                        start = ini[1];
                        end = ini[n];
                        ans[1] = start;
                        ans[n] = end;
                        if(tofopr >= 0){
                            tofopr = isok(n,newc);
                            jg.insert(tofopr);
                        }
                    }
                    if(i == c + 1){
                        start = ini[1] -1;
                        end = ini[n];
                        if(start >= 0){
                            ans[1] = start;
                            ans[n] = end;
                            tofopr = isok(n,newc);
                            if(tofopr >= 0){
                                tofopr += 1;
                                jg.insert(tofopr);
                            }
    
                        }
                        start = ini[1];
                        end = ini[n]+1;
                        ans[1] = start;
                        ans[n] = end;
                        tofopr = isok(n,newc);
                        if(tofopr >= 0){
                            tofopr += 1;
                            jg.insert(tofopr);
                        }
                    }
                    if(i == c + 2){
                        start = ini[1] - 1;
                        end = ini[n] + 1;
                        if(start >= 0){
                            ans[1] = start;
                            ans[n] = end;
                            tofopr = isok(n,newc);
                            if(tofopr >= 0){
                                tofopr += 2;
                                jg.insert(tofopr);
                            }
                        }
                    }
    
                }
    
            }
            if(jg.empty()){
                printf("-1");
            }
            else
            {
                auto it = jg.begin();
                printf("%d",*it);
            }
        }
        return 0;
    }

      而神犇的代码如下,思路是一致的,但是神犇找最小的方法很特殊!代码如下:

     

    #include <bits/stdc++.h>
    
    using namespace std;
    const int maxn = 2e5 + 100;
    typedef long long ll;
    
    ll n, num[maxn];
    
    void init() {
        scanf("%lld", &n);
        for (int i = 0; i < n; i++) 
            scanf("%lld", &num[i]);
    }
    
    ll get_ans(ll tol) {
        ll cnt[3],st;
        cnt[0] = cnt[1] = cnt[2] = 0;
        for(int i=0;i<3;i++) {
            if(i == 0) st = num[0]-1;
            else if(i == 1) st = num[0];
            else st = num[0] + 1;
    
            for (ll j = 0; j < n; j++) {
                if(abs(num[j]-st) > 1) {
                    cnt[i] = INT_MAX;
                    break;
                }
                cnt[i] += abs(num[j] - st);
                st += tol;
            }
        }
        if(cnt[0] == cnt[1] && cnt[1] == cnt[2] && cnt[0] == INT_MAX) //无法组成等差数列返回-1
            return -1;
        return min(cnt[0], min(cnt[1], cnt[2]));
    }
    
    int main() {
        init();
        ll Min = INT_MAX,tol;
        tol = num[1]-num[0];
        ll ans = get_ans(tol);
        if(ans >= 0)
            Min = min(Min, ans);
        for (int i = 1; i <= 2; i++) {
            ans = get_ans(tol-i);
            if (ans >= 0)
                Min = min(Min, ans);
    
            ans = get_ans(tol+i);
            if (ans >= 0)
                Min = min(Min, ans);
        }
    
        if (Min == INT_MAX)
            printf("-1");
        else
            printf("%lld", Min);
    
    
        return 0;
    }
  • 相关阅读:
    excel VBA构造正则函数(双参数)
    excel VBA构造函数就是这么简单
    excel VBA中正则模块vbscript.regexp的用法
    excel VBA构造正则函数(单参数)
    USB 设备插拔事件处理
    MySQL 修改 root 密码命令
    函数指针
    串口编程需要注意的地方
    写开机自启动程序应该注意的一点
    C++ 中 delete 和 delete[] 的区别
  • 原文地址:https://www.cnblogs.com/doubest/p/10185836.html
Copyright © 2011-2022 走看看