cursor: url(https://files-cdn.cnblogs.com/files/zouwangblog/cursor.ico),auto;

JZOJ5872-小A的任务

题目描述

输入格式

第一行,为任务数n
第一行,n个数,第i个数为任务i的价值Si

输出格式

第一行,为最大优美程度
第二行,为选择的任务数

样例一

input

3
1 2 3

output

624
3

限制与约定

对于10%的数据,保证n<=5
对于40%的数据,保证N<=10
对于70%的数据,保证N<=500
对于100%的数据,保证N<=10^7,1<=si<=n

 

题解:

这题首先必须要知道一个结论,不知道就只能用n3的方法来做,只有70分(真亏是T1....)

这个结论很简单,就是上面两个算分的式子,第一个大于等于第二个,且取等条件是Si=Sj=Sk。

怎样证明呢,比较简单的一种就是柯西不等式(停课选手表示知道也无奈)。

首先柯西不等式(一般式)的结论是:

 

对于两组数a,b(组内数的个数相同)有

至于为什么,之前上课时就说过可以用向量证明二维柯西不等式,具体的自己去看吧。。

因此由柯西不等式可得:

 

所以除非所有元素相等,全部都是要选的。

接下来把第一个式子转成两部分计算相加即可,下面是co的另一份题解(懒)

 

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=1e9+7,N=1e7+7;
int n;
ll a[N],ans=0,inv=0;
ll ksm(ll y,int b){
    ll x=1;
    while(b){
        if(b&1) x=x*y%mod;
        y=y*y%mod; b>>=1;
    }
    return x;
}
int main()
{
    int i;
    scanf("%d",&n);
    ll t=0,tt=0,p=3*n*n%mod; bool b=1;
    for(i=1;i<=n;i++){
        scanf("%lld",&a[i]);
        ans=(ans+p*a[i]%mod)%mod;inv=(inv+ksm(a[i],mod-2))%mod;
        if(i>1&&tt!=a[i])b=0;
        tt=a[i];
        a[i]=a[i]*a[i]%mod;
    }
    t=n*6;for(i=1;i<=n;i++) ans=(ans+t*inv%mod*a[i]%mod)%mod;
    if(b)printf("%lld\n0",ans);
    else printf("%lld\n%d",ans,n);
} 
View Code

 

posted @ 2018-09-30 19:48  Art-Yrr  阅读(252)  评论(0)    收藏  举报