本文主要是介绍2016 Multi-University Training Contest 2-1001---HDU 5734 Acperience,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
- 题目链接:HDU 5734
- 题意:有一个向量: W=(w1,w2,...,wn) ,求一个数 α(α≥0) 和一个 B=(b1,b2,...,bn) 向量,使得 ∥W−αB∥2 的值最小。
注: ∥X∥=x21+⋯+x2n−−−−−−−−−−−√ ,其中 X=(x1,x2,...,xn) ,其实就是向量的模长。 - 题解:
官方题解:
展开式子可以得到:|W−αB|2=α2∑i=1nb2i−2α∑i=1nwibi+∑i=1nw2i
由于 bi∈+1,−1 那么 ∑i=1nb2i=n , 显然 c=∑i=1nw2i 也是常数. 转化成求 α2n−2α∑i=1nwibi+c 的最小值.
对于固定的 α≥0 , 只要 ∑i=1nwibi 最大就好了. 显然 bi=sign(wi) (符号函数)的时候, ∑i=1nwibi=∑i=1n|wi| 最大.
进一步的, 上面显然是一个关于\alphaα的二次方程, 于是当 α=1n∑i=1nwibi=1n∑i=1n|wi| 时, 取到最大值.
化简下, 可以得到最小值是 ∑ni=1w2i−1n(∑i=1n|wi|)2 .
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int MAX=100000+10;
int a[MAX];
int main()
{//freopen("in.txt","r",stdin);//freopen("out.txt","w",stdout);int T;scanf("%d",&T);while(T--){int n;scanf("%d",&n);LL sum1=0,sum2=0;for(int i=0;i<n;i++){scanf("%d",&a[i]);sum1+=1ll*a[i]*a[i];sum2=sum2+abs(a[i]);}LL gcd=__gcd(sum2*sum2,(LL)n);cout<<sum1*n/gcd-sum2*sum2/gcd<<"/"<<n/gcd<<endl;}return 0;
}
这篇关于2016 Multi-University Training Contest 2-1001---HDU 5734 Acperience的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!