zoukankan      html  css  js  c++  java
  • [gym102822I]Invaluable Assets

    令$f(x)=frac{x^{2}+c}{x}$,换言之即$x$物品的性价比的倒数

    对其求导即$f'(x)=1-frac{c}{x^{2}}$,其导数严格递增,换言之即是一个严格下凸函数,记$x_{0}$为其最小值的位置,那么不难证明$x_{0}=lfloorsqrt{c} floor$或$lceilsqrt{c} ceil$

    性质1:存在最优解,使得其不存在一个$xge 2x_{0}$的物品

    对于$xge 2x_{0}$的物品,考虑拆分为$x_{0}+(x-x_{0})$,代入化简即求证$2x_{0}(x-x_{0})ge c$,由于$xge 2x_{0}$,即要求$2x_{0}^{2}ge c$,显然成立

    性质2:存在最优解,使得不存在若干个体积非$x_{0}$的物品,且体积和为$x_{0}$的倍数

    将这些物品用若干个$x_{0}$来代替是不劣的——

    从性价比的角度来考虑,对于两个物品合并后的性价比显然在合并前两物品的性价比区间中

    由于$x_{0}$的性价比最大(性价比倒数最小),因此其余物品合并后性价比一定不超过$x_{0}$,而仅含有$x_{0}$的话一定恰好为$x_{0}$的性价比,即不劣

    推论1:存在最优解,使得不存在$x_{0}$个体积非$x_{0}$的物品

    对于$x_{0}$个物品,必然会存在一个子集使得其体积和为$x_{0}$的倍数

    推论2:存在最优解,使得体积非$x_{0}$的物品和不超过$3c$

    根据推论1,至多$x_{0}-1$个物品,根据性质1,每一个物品体积不超过$2x_{0}-1$,显然$(x_{0}-1)(2x_{0}-1)le 3c$,即成立

    设$V$是需要填充的体积($max(k-a_{i},0)$),对$Vle 3c$用背包预处理,复杂度为$o(csqrt{c})$(物品体积小于$2x_{0}$),接下来考虑$V>3c$的问题:

    性质3:存在一组最优解,使得其至多选择两种体积的物品,且为$x$和$x+1$

    当我们同时选择了$x$和$y$两个物品,且满足$x+1le y-1$,根据凸性(或代入展开),不难得到选择$x+1$和$y-1$一定不劣,即可以使得其不存在

    推论3:当$V>3c$,$x=x_{0}$或$x_{0}-1$

    若$x e x_{0}$或$x_{0}-1$,即$x_{0} otin {x,x+1}$,那么即不为$x_{0}$的物品体积和大于了$3c$,矛盾

    以$x=x_{0}$为例,先选择$s$个$x_{0}$,再将其中$V-sx_{0}$个个物品变为$x_{0}+1$,由于$x_{0}+1$的物品个数要小于$x_{0}$(根据推论1),因此是$s$是唯一的

    通过上述,我们填充$V$体积的最优解可以$o(1)$得到,复杂度为$o(csqrt{c}+nq)$,无法通过

    接下来,由于$k$和$a_{i}$是随机的,因此$Vle 3c$的概率为$o(frac{c}{1e9})$,对于这一类暴力统计,复杂度为$o(csqrt{c}+frac{nqc}{1e9})$(具体可以将$k$排序后利用单调性来找)

    对于$V>3c$的情况,继续分析不难发现答案即
    $$
    (x_{0}^{2}+c)frac{V-r}{x_{0}}+min((2x_{0}+1)r,(x_{0}^{2}+c)+(x_{0}-r)(2x_{0}-1))
    $$
    (其中$Vequiv r(mod x_{0})$且$0le r<x_{0}$)

    后者仅与$r$有关,利用单调性,维护出$a_{i}$模$x_{0}$的每一类中的个数以及$V$的和,即可做到$o(qsqrt{c})$的复杂度

    最终总复杂度为$o(csqrt{c}+frac{nqc}{1e9}+qsqrt{c})$,可以通过

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 100005
     4 #define C 10005
     5 #define X0 105
     6 #define ll long long
     7 #define fi first
     8 #define se second
     9 pair<int,int>q[N];
    10 int t,n,c,m,x0,a[N],f[C*3],sum1[X0];
    11 ll sum2[X0],ans[N];
    12 int cost(int k){
    13     return 1LL*k*k+c;
    14 }
    15 int calc(int k){
    16     return min((2*x0+1)*k,cost(x0)-(x0-k)*(2*x0-1));
    17 }
    18 int main(){
    19     scanf("%d",&t);
    20     for(int ii=1;ii<=t;ii++){
    21         scanf("%d%d%d",&n,&c,&m);
    22         x0=(int)sqrt(c);
    23         if (cost(x0)*(x0+1)>cost(x0+1)*x0)x0++;
    24         memset(f,0x3f,sizeof(f));
    25         f[0]=0;
    26         for(int i=1;i<2*x0;i++)
    27             for(int j=i;j<=3*c;j++)f[j]=min(f[j],f[j-i]+cost(i));
    28         for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    29         sort(a+1,a+n+1);
    30         for(int i=1;i<=m;i++){
    31             scanf("%d",&q[i].fi);
    32             q[i].se=i;
    33         }
    34         sort(q+1,q+m+1);
    35         memset(sum1,0,sizeof(sum1));
    36         memset(sum2,0,sizeof(sum2));
    37         memset(ans,0,sizeof(ans)); 
    38         for(int i=1,l=1,r=1;i<=m;i++){
    39             while ((l<=n)&&(a[l]<q[i].fi-3*c)){
    40                 sum1[a[l]%x0]++;
    41                 sum2[a[l]%x0]+=a[l];
    42                 l++;
    43             }
    44             while ((r<=n)&&(a[r]<=q[i].fi))r++;
    45             for(int j=l;j<r;j++)ans[q[i].se]+=f[q[i].fi-a[j]];
    46             for(int j=0;j<x0;j++){
    47                 int jj=(q[i].fi-j)%x0;
    48                 ans[q[i].se]+=1LL*sum1[j]*calc(jj)+(1LL*sum1[j]*(q[i].fi-jj)-sum2[j])/x0*cost(x0);
    49             }
    50         }
    51         printf("Case #%d:
    ",ii);
    52         for(int i=1;i<=m;i++)printf("%lld
    ",ans[i]);
    53     } 
    54 }
    View Code
  • 相关阅读:
    《大道至简》读后感
    PowerBuilder学习笔记之1开发环境
    PowerBuilder学习笔记之14用户自定义对象
    查询数据库大小的代码
    JAVA基础_修饰符
    SQLSERVER查询存储过程内容
    Asp.Net WebAPI中Filter过滤器的使用以及执行顺序
    运算符
    判断(if)语句
    变量的命名
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/14361468.html
Copyright © 2011-2022 走看看