SDUSTOJ 1795 哆啦A梦的程序(思路题)

Description

哆啦A梦很喜欢写代码。在缩代码方面,他是一位身经百战的老手。世界各地的OJ上,很多题的最短解答排行榜都有他的身影。这令他感到十分愉悦。


最近,他突然发现,很多时候自己的程序明明看起来比别人的更短,实际代码量却更长。这令他感到很费解。经过一番研究,原来是因为他每一行的缩进都全是由空格组成的,大量的空格让代码量随之增大。

现在设哆啦A梦有一份 n 行的代码,第 i 行有 ai 个空格作为缩进。

为解决这一问题,哆啦A梦要给自己文本编辑器设定一个正整数的默认TAB宽度 x,然后对于每一行,编辑器从头至尾不断把连续 x 个空格替换成一个TAB,直到剩余空格数不足 x 个。

最终缩进所占代码量为空格数与TAB数的和。请你帮哆啦A梦选择一个合适的 x,使得缩进所占代码量最小。

Input

多组数据,对于每一组数据

第一行一个正整数 n,表示代码行数。

接下来 n 行,第 i行一个正整数 ai,为初始时第 i行缩进的空格个数。

n<=10^6,ai<=10^6

Output

一行一个整数,表示缩进所占代码量最小是多少。

Sample Input

3
5
8
8

Sample Output

6

思路:
这道题是山科第三届校赛的题,我们队一路领先,直到最后20分钟被这道题绝杀了。。
真的是一时想不出好的思路,练得太少了,弱就是弱
这道题据出题人说正解是nlogn的复杂度,想好了思路就很简单,但是三分答案也能过
赛后整理了一下,说一下我的做法吧
枚举x(o(n)),每一层以x长度分段
也就是for(int j=1;j*x<=n;j++)这样分
每一个x长度的段里所有数的个数和所有数的和都可以o(n)预处理
然后当前这一个x的ans加上个数*j(除法的值),再加上这一层的和减去着一层的个数*i*j(取模的值)
这样每一个x都可以给出一个确定的答案
时间复杂度就是O(n/1+n/2+n/3+...+n/n)=O(nlogn)的了
可能我写的比较复杂、、比标程长,也慢(实力差距~)
/* ***********************************************
Author        :devil
Created Time  :2016/4/26 16:10:39
************************************************ */
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <cmath>
#include <stdlib.h>
using namespace std;
typedef long long LL;
const int N=2e6+7;
int a[N],b[N];
long long sum[N];
int main()
{
    //freopen("in.txt","r",stdin);
    int n,x;
    while(~scanf("%d",&n))
    {
        int ma=0;
        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
        memset(sum,0,sizeof(sum));
        for(int i=0;i<n;i++)
        {
            scanf("%d",&x);
            ma=max(ma,x);
            a[x]++;
        }
        for(int i=1;i<=ma*2+1;i++)
        {
            sum[i]=sum[i-1]+a[i]*i;
            b[i]=b[i-1]+a[i];
        }
        LL ans=1e12+10;
        for(int i=1;i<=ma;i++)
        {
            LL now=sum[i-1];
            for(int j=1;i*j<=ma;j++)
                now=now+(b[i*(j+1)-1]-b[i*j-1])*j+sum[i*(j+1)-1]-sum[i*j]-(b[i*(j+1)-1]-b[i*j])*j*i;
            ans=min(ans,now);
        }
        printf("%lld\n",ans);
    }
    return 0;
}

 

posted on 2016-04-26 16:11  恶devil魔  阅读(344)  评论(0编辑  收藏  举报

导航