There are some positive integer numbers, and you want to divide them into two nonempty sets (every integer should be in and only in one set) and get a value descripted below:
Assume that set A has n1 numbers A1, A2, ...,An1; set B has n2 numbers B1, B2, ...Bn2.
Let
Then
We want to know the largest ans.
输入
The first line of the input is an integer T (T <= 20), which stands for the number of test cases you need to solve.
Every test case begins with an integer N (2 <= N <= 10000), then followed by N positive integers on the next line, these numbers will not exceed 1000.
输出
For every test case, you should output "Case #k: " first, where k indicates the case number and starts at 1. Then output the answer rounded to two digits after the decimal point. See sample for more details.
样例输入
2
3
1 1 1
3
1 2 3
样例输出
Case #1: 0.00
Case #2: 7.25
思路:
将输入数据从小到大排列后, 问题为求一个位置i (0<=i<n), 使得以i为界的两个部分(第i个位置的元素属于第一部分)满足目标函数:
max
如果线性搜索i ,计算每个ans求得最大值, 遍历时间为O(n),计算时间为O(n),总的时间复杂度为O(n2), 在10000的数据规模下会超时。
此处,需要将目标函数进行拆分转义,得到化简后的目标函数为:
所有元素的平方和(定值)+ n1*v2*v2+n2*v1*v1-2*v1*v2*n ;
其中 ,n1= i+1,n2=n-i-1 . v1,v2也容易求得。
这样计算的时间复杂度降为O(1),总的时间复杂度为O(n)。
代码:
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
int t,k,i,j,sum,n;
int s[10001],num[10001];
double max=-999999,temp,result;
double a,b,aa,bb;
double e=0.000001;
int mark=0;
cin>>t;
for(k=1;k<=t;k++)
{
cin>>n;
sum=0;
temp=0;
max=0;
result=0;
for(i=0;i<n;i++)
{
cin>>num[i];
temp+=num[i]*num[i];
}
sort(num,num+n);
for(i=0;i<n;i++)
{
sum+=num[i];
s[i]=sum;
}
for(i=0;i<n-1;i++)
{
a=1.0*s[i]/(i+1);
b=1.0*(sum-s[i])/(n-i-1);
// cout<<"*"<<a<<" "<<b<<endl;
result=temp+1.0*((i+1)*b*b+(n-i-1)*a*a-2*a*b*n);
if(result>max)
{
// cout<<i<<" "<<temp<<endl;
max=result;
mark=i;
aa=a;
bb=b;
// cout<<aa<<bb<<endl;
}
}
printf("Case #%d: %.2lf\n",k,max);
}
}