codeforces731F (思维)


题意:给出一个数列.在数列中选取一个数,然后求把数列中的数变成小于他们的并且是这个数的倍数的数,求变化之后的数列的和最大值。

思路: 将每个数的个数记录下来,用前缀和记录下来。然后枚举每一个数,以他们的倍数进行计算出选取这个数后数列和。

以他们的倍数计算是:

比如以枚举a[i] ,那么在 a[i] * j 和 a[i] * (j + 1) - 1这个区间的数经过变换之后都是a[i] * j ,所以我们只要知道这些数的个数就能计算了,个数的话就要用到刚刚计算出的前缀和了。


PS :为了避免超时,同一个a[i]枚举过就不要枚举,所以用一个vis数组标记一下/。


#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e6 + 10;
#define INF 0x3f3f3f3f
typedef pair<int,int> P;
typedef long long ll;
int a[maxn];
int cnt[maxn];
ll sum[maxn + 100];
int n;
bool vis[maxn];
int main()
{
    while( ~ scanf("%d",&n))
    {
        memset(cnt,0,sizeof(cnt));
        memset(vis,false,sizeof(vis));
        int maxs = 0;
        for(int i = 1; i <= n;i ++)
            scanf("%d",&a[i]),cnt[a[i]] ++,maxs = max(maxs,a[i]);
        sum[0] = 0;
        for(int i = 1; i <= maxn; i ++)
            sum[i] = sum[i - 1] + cnt[i];
        ll ans = 0;
        for(int i = 1; i <= n; i ++)
        {
            if(vis[a[i]])continue;vis[a[i]] = true;
            ll temp = 0;
            for(int j = 2; (j  - 1)* a[i] <= maxs; j ++)
            {

                if(j * a[i] > maxs)
                {
                    temp += (sum[maxs ] - sum[(j - 1) * a[i] - 1]) * a[i] * (j - 1);
                }
                else
                {
                    temp += (sum[j * a[i] - 1] - sum[a[i]*(j - 1) - 1] )* a[i] * (j - 1);
                }

            }
            ans = max(ans,temp);
        }
        printf("%I64d\n",ans);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值