牛客多校联赛第二场部分题解

G题 Link with Monotonic Subsequence

题目大意

给定一个长度为n,元素为1~n的数列,要求取得一种排列情况使得最长非连续升序和降序子序列两者的较大值取到最小。

思路

将长度为n的序列分为n段长度为n的序列,每段倒置,末尾不足n的一段视为单独一段。

例如长度为9的序列改为3 2 1 6 5 4 9 8 7

长度为11的序列为4 3 2 1 8 7 6 5 11 10 9

操作后得出最小的较大值n

代码

c++

#include<iostream>
#include<cmath>
using namespace std;
int main() {
    int t;
    cin >> t;                       \\t为用例个数
    for (int i = 0; i < t; i++) {
        int n;
        cin >> n;
        int g = (int)sqrt(n - 1) + 1;                \\g为n
        int temp = g;
        int k = 0;
        while (k < n) {                               \\while循环给数列数组赋值,k为数组下标
            cout << temp << " ";
            if (temp % g == 1) {
                if (temp + 2 * g - 1 > n)temp = n;
                else temp += 2 * g - 1;
            }
            else temp--;
            k++;
        }
        cout << endl;
    }
}

J题 LInk with Arithmetic Progression

题目大意

给定一个数列,其中每个数都有一个修改机会,使得数列为等差数列,要求修改值的平方和达到最小值。

思路

将数组第i个值ai视为指标坐标系上x=i,y=ai的点,即求一个较为贴合坐标系上所有点的直线,参考数学方法线性回归。

 代码

import java.util.Scanner;

public class J {
    public static void main(String[] args) {
        Scanner input =new Scanner(System.in);
        int t=input.nextInt();
        for(int i=0;i<t;i++){
            int n= input.nextInt();
            int[] num=new int[n];
            for(int j=0;j<n;j++){
                num[j]= input.nextInt();
            }
            double ave=GetAve(num);
            double b=GetB(num,ave);
            double a=GetA(num,b,ave);
            double sum=GetSum(num,b,a);
            System.out.println(sum);
        }
    }
    public static double GetA(int[] num,double b,double ave){      \\计算'a'
        return ave-b*(num.length+1)/2.0;
    }
    public static double GetB(int[] num,double ave){   \\计算'b'
        double n=0;
        double m=0;
        for(int i=1;i<= num.length;i++){
            n+=(i-(num.length+1)/2.0)*(num[i-1]-ave);
            m+=Math.pow(i-(num.length+1)/2.0,2);
        }
        return n/m;
    }
    public static double GetSum(int[] num,double b,double a){    \\计算平方和
        double sum=0;
        for(int i=1;i<= num.length;i++){
            sum+=Math.pow(b*i+a-num[i-1],2);
        }
        return sum;
    }
    public static double GetAve(int[] num){          \\计算数组平均值
        double sum=0;
        for(int i=0;i<num.length;i++){
            sum+=num[i];
        }
        return sum/num.length;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值