您的位置:首页 > 其它

acdream Divide Sum

2014-09-01 14:53 267 查看

Divide Sum

Time Limit: 2000/1000MS (Java/Others)Memory Limit: 128000/64000KB (Java/Others)
[align=center]SubmitStatisticNext Problem[/align]

Problem Description

long long ans = 0;
for(int i = 1; i <= n; i
++)
for(int j = 1; j <= n; j ++)
ans += a[i] /
a[j];
给出n,a[1]...a
,求ans

Input

不超过5组数据,每组数据:第一行n(1 <= n <= 10^5)第二行n个数,a[1].. a
(1 <= a[i] <= 10^5)

Output

每组数据一行,ans

Sample Input

5
1 2 3 4 5

Sample Output

27

用 n/i = n/(i+k)的方法找上届和下届,统计出现次数,超时。
贴一个代码:
/*
* this code is made by 987690183
* Problem: 1181
* Verdict: Time Limit Exceeded
* Submission Date: 2014-09-01 12:47:21
* Time: 1000MS
* Memory: 2848KB
*/
#include<iostream>
#include<stdio.h>
#include<cstring>
#include<cstdlib>
using namespace std;

int date[100002];
int num[100002];
int sum1[100002];
int main()
{
int n;
int maxn;
while(scanf("%d",&n)>0)
{
memset(num,0,sizeof(num));
maxn = -1;
for(int i=1;i<=n;i++) {
scanf("%d",&date[i]);
num[date[i]] ++;
if(date[i]>maxn) maxn = date[i];
}
sum1[0]=0;
for(int i=1;i<=maxn;i++)
sum1[i] = sum1[i-1]+num[i];

long long sum = 0;
if(n>900)
for(int i=1;i<=maxn;i++)
{
if(num[i]>0)
for(int j=1,la = 0;j<=i;j = la+1)
{
la = i/(i/j);
sum = sum + (long long)(sum1[la]-sum1[j-1])*(i/j)*num[i];
}
}
else
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
sum = sum+date[i]/date[j];
}
}
printf("%lld\n",sum);
}
return 0;
}
View Code
为什么超时,我很疑惑,因为最坏的情况下1-10^5个数字,只出现一次。时间应该也是n*sqrt(n);和ac代码比较也是一样吧。超时代码唯一不同的是有许多*,/的运算。ac代码:只有+思路:统计数字x的出现次数num[],然后求前n项和用sum1[]保存然后改变一下思路,求对于第i个数字来说,被多少数字/过,举例:i = 2,n =9;那么首先[2-9]里的数字能除i+[8-9]能除i.这有数字8,9就算了两次。知道统计第i个数字被多少数字/过,就不难理解。
/*
* this code is made by 987690183
* Problem: 1181
* Verdict: Accepted
* Submission Date: 2014-09-01 14:41:17
* Time: 72MS
* Memory: 2848KB
*/
#include<iostream>
#include<stdio.h>
#include<cstring>
#include<cstdlib>
#include<math.h>
using namespace std;

int date[100002];
int num[100002];
int sum1[100002];
int main()
{
int n;
int maxn;
while(scanf("%d",&n)>0)
{
memset(num,0,sizeof(num));
maxn = -1;
for(int i=1;i<=n;i++) {
scanf("%d",&date[i]);
num[date[i]] ++;
if(date[i]>maxn) maxn = date[i];
}
sum1[0]=0;
for(int i=1;i<=maxn;i++)
sum1[i] = sum1[i-1]+num[i];

long long ans = 0;
long long sum = 0;
for(int i=1;i<=maxn;i++)
{
if(num[i])
{
ans = 0;
for(int j=i-1;j<=maxn;j=j+i)
ans = ans+n-sum1[j]; //!!!!
sum = sum + ans*num[i];
}
}
printf("%lld\n",sum);
}
return 0;
}

                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: