g题
1.题目大意:构造长度为n的排列p,使得max{lis(p),lds(p)}最小。
其中lis*(p)为p的最长上升子序列的长度,lds(p)为p的最长下降子序列的长度.
2.分析:我们应构造一个sqrt(n)的序列,此时满足题目要求.
3.代码:
#include <cmath>
using namespace std;
int main(){
int t;
cin>>t;
while(t--){
int n;
scanf("%d",&n);
int num=ceil(sqrt(n));
if(num*num==n){
for(int i=num;i<=n;i+=num){
int temp=i;
for(int j=0;j<num;j++){
cout<<temp--;
if(!(i==n && j==num-1)) cout<<' ';
}
}
cout<<endl;
}
else{
int last=n%num;
for(int i=num;i<=n-last;i+=num){
int temp=i;
for(int j=0;j<num;j++){
cout<<temp--<<" ";
}
}
for(int i=0;i<last;i++){
cout<<n--<<" ";
}
cout<<endl;
}
}
return 0;
}
j题
1.题目大意:给定一个数列,求一个新的等差数列,使得两者差的平方之和最小
2.分析:我们组当时是用java的线性回归去做的。后面用c++去提交发现,答案错误,可能是精度导致(?
3.代码:
public class Main {
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){
return ave-b*(num.length+1)/2.0;
}
public static double GetB(int[] num,double ave){
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;
}
}