Codeforces Round #376 (Div. 2) F Video Cards

来源:互联网 发布:php向数据库中添加数据 编辑:程序博客网 时间:2024/06/04 18:28

本题大意如下:
给出一个长度为n的数组a
选取a数组中的任意一个数为基底x
求取Σa[i]/x*x的最大值

博主是弱鸡。。
比赛的时候没写出来这题,Y的这题有200多个人A啊,
幸好Rating没掉太多

计算Σa[i]/x*x的最大值
由于数据大小是200000
直接for肯定是会TLE的

但是我们想到,对于每一个基底x
在x*k~x*(k+1)-1这一区间内的数都可以看成x*k来相加
所以我们可以用一个前缀和数组sum来维护这个值
sum[i]代表小于等于i的数有多少个
之后对于每个a[i]为基底的情况,每次for的时候加上a[i]就行了
但是博主这样交了几次都在第38组数据TLE了
于是需要剪枝
很容易可以想到的是
对于某一个基底a[i]和它的倍数a[i]*k而言
必定有res[a[i]*k]<=res[a[i]]
所以我们可以将a[i]的倍数全部mark掉,这样速度就会快很多、
于是就A掉了
只有31ms,只能说数据坑

AC代码如下:

#include<stdio.h>#include<string.h>#include<string>#include<algorithm>#include<iostream>#include<queue>#include<vector>#include<math.h>#include<stdlib.h>#include<map>#include<ctype.h>using namespace std;#define LL long long#define M 200005#define oo 2000000000int a[M],cnt[M],sum[M],mark[M];void Rd(int &res){    char c;res=0;    while(c=getchar(),!isdigit(c));    do res=(res<<3)+(res<<1)+(c^48);    while(c=getchar(),isdigit(c));}int main(){    int n,mx=0;LL ans=0;    scanf("%d",&n);    for(int i=1;i<=n;i++){        Rd(a[i]);//加个读入挂,读入数据有点多(据说scanf读入是log级别的)        mx=max(mx,a[i]);        cnt[a[i]]++;        }sort(a+1,a+n+1);//不排序的孩纸是作死    for(int i=1;i<=mx;i++)sum[i]=sum[i-1]+cnt[i];//前缀和!!!    for(int i=1;i<=n;i++){        if(mark[a[i]])continue;        LL res=0;        for(int j=a[i];j<=mx;j+=a[i]){//跳!跳!跳!            mark[j]=1;//最重要的mark            int r=j+a[i]-1;            if(mx<r)r=mx;//注意上界不能超过mx            res+=1ll*j*(sum[r]-sum[j-1]);//孩子别忘了longlong        }if(res>ans)ans=res;    }cout<<ans<<endl;    return 0;}
2 0