关闭

TJU-4113- Determine X(数学题)

标签: acm数学
162人阅读 评论(0) 收藏 举报
分类:

给出数列Ai~An,求

F(x)=i=1N(Aix+Aimodx)

的最小值。


教训:因为不需要使用long long的数组开成了long long,TLE了好多次。

做法:

预处理出f[n](小于等于n有多少个数)和s[n](小于等于n的数之和)。

暴力枚举x(从2到最大的一项),对于每个x,可以把这些数分成若干段,每段具有类似的性质。即Ai / x的值相同。

例如,数列为 2,4,5,6,8,9,13,14.........,当x=5,2,4可以分为1组,5,6可以分为一组,8,9为一组,13,14为一组

枚举Ai/x的值,就可以O(1)计算出这段中Ai/x+Ai%x的值。(tips:A%X=A-(A/X)×X)。设N=max(Ai),均摊的复杂度为O(NlogN)。

#include<cstdio>
#include<cstring>
#include<algorithm>
typedef long long LL;
using namespace std;


const int MAXM=1E6;
int a[MAXM+5],f[MAXM+5];
LL  s[MAXM+5];

void work()
{
    int i,j,k,t,m,n,maxa;
    LL ans,sum,x,temp,lim;
    maxa=0;

    scanf("%d",&n);
    for(i=0;i<n;i++) scanf("%d",&a[i]),maxa=max(maxa,a[i]);
    for(i=0;i<=maxa;i++) s[i]=f[i]=0;
    for(i=0;i<n;i++)
    {
        f[a[i]]++;
        s[a[i]]+=(LL)a[i];
    }

    for(i=1;i<=maxa;i++)
    {
        f[i]+=f[i-1];
        s[i]+=s[i-1];
    }
    ans=s[maxa];
    for(k=2;k<=maxa;k++)
    {
        sum=0;
        for(i=0;i*k<=maxa;i++)
        {
            int x=max(0,i*k-1);
            int y=min(maxa,(i+1)*k-1);
            sum+=(LL)i*(LL)(f[y]-f[x]);
            sum+=s[y]-s[x]-(LL)(f[y]-f[x])*(LL)i*(LL)k;
            if(sum>=ans) break;
        }
        ans=min(ans,sum);
    }
    printf("%lld\n",ans);
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--) work();
    return 0;
}


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:25479次
    • 积分:1039
    • 等级:
    • 排名:千里之外
    • 原创:81篇
    • 转载:3篇
    • 译文:0篇
    • 评论:2条
    文章分类
    最新评论