ACDream - Divide Sum

先上题目:

Divide Sum

Time Limit: 2000/1000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others)

SubmitStatus

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[n],求ans

Input

不超过5组数据,每组数据:

第一行n(1 <= n <= 10^5)

第二行n个数,a[1].. a[n] (1 <= a[i] <= 10^5)

Output

每组数据一行,ans

Sample Input

5
1 2 3 4 5

Sample Output

27

  比赛的时候想的方法是枚举除数的倍数,然后用lower_bound和upper_bound求出那个范围里面的得到同一个商的数的个数,然后相乘得到一部分的结果,结果超时了。后来在思考一下,发现好像时间复杂度并没有降到nlogn而是变成了(n^2)logn,然后就想到的另一种nlogn的方法,但是在脑子想出来的时候觉得跟之前的方法基本一样,时间复杂度并没有任何变化。结果比赛结束前基本没有动过,结束以后听题解,结果ZZ说的方法就是我想的那种······又被坑了一回,这回也是自己坑自己。

  思路:先对所有的数按从小到大排序,然后根据分析我们可以发现,如果一个数除以一个比它大的数,那么结果绝对为0,而一个数被比它大的数除的时候,我们可以枚举这个除数的倍数,然后得到在某一倍数的范围里面的数的个数,将个数乘以枚举的商,在求和就是答案了。比赛的时候求范围里面的数的个数我用的方法是求上下界然后相减求个数,结果TLE了3次,ZZ将的方法是用树状数组统计,这个我在比赛的时候也有想过,但是觉得枚举的环节比较耗时间所以就没有动手写。

  总的来说前6场个人赛有不少都是自己坑自己,不少的题都是会做的,结果要么因为敲了代码以后,一直觉得是代码没有问题,但是一直WA或者TLE以后就觉得是思路有问题,最终的结果是有几场吃了蛋,剩下的几场也是被吊打啊T_T。感觉暑假开始以后就一直很没有状态,敲一段代码都错漏百出,有的时候真的感觉没脸见人了(捂脸)。看来要快点加油才行啊。

上代码:

 1 /*
 2 * this code is made by sineatos
 3 * Problem: 1181
 4 * Verdict: Accepted
 5 * Submission Date: 2014-07-31 23:29:05
 6 * Time: 428MS
 7 * Memory: 1868KB
 8 */
 9 #include <cstdio>
10 #include <cstring>
11 #include <algorithm>
12 #define lowbit(x) (x&(-x))
13 #define MAX 100002
14 #define ll long long
15 using namespace std;
16
17 int a[MAX];
18 int c[MAX];
19 int n;
20
21 const int all=MAX-2;
22
23 void add(int x,int e){
24     for(;x<=all;x+=lowbit(x)){ c[x]+=e; }
25 }
26
27 int sum(int x){
28     int ans=0;
29     for(;x>0;x-=lowbit(x)) ans+=c[x];
30     return ans;
31 }
32
33 int main()
34 {
35     ll sum0,ans,lans;
36     //freopen("data.txt","r",stdin);
37     while(scanf("%d",&n)!=EOF){
38         memset(c,0,sizeof(c));
39         sum0=0;
40         for(int i=0;i<n;i++){
41             scanf("%d",&a[i]);
42             add(a[i],1);
43             sum0+=a[i];
44         }
45         sort(a,a+n);
46         ans=0;
47         lans=0;
48         for(int i=0;i<n;i++){
49             if(a[i]==1){
50                 ans+=sum0;
51             }else if(i!=0 && a[i]==a[i-1]){
52                 ans+=lans;
53             }else{
54                 int k,e=1;
55                 lans=0;
56                 for(int j=a[i];j<=a[n-1];j+=a[i]){
57                     k=j+a[i];
58                     if(k>a[n-1]) k=a[n-1]+1;
59                     int q=sum(k-1)-sum(j-1);
60                     lans+=(ll)q*e;
61                     e++;
62                 }
63                 ans+=lans;
64             }
65         }
66         printf("%lld\n",ans);
67     }
68     return 0;
69 }

/*Divide Sum*/

ACDream - Divide Sum,布布扣,bubuko.com

时间: 2024-10-22 15:36:44

ACDream - Divide Sum的相关文章

Divide Sum 比赛时竟然想不出。。。。。。。

Divide Sum Time Limit: 2000/1000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others) SubmitStatus 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[n],求an

ACDream - Power Sum

先上题目: Power Sum Time Limit: 20000/10000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others) SubmitStatus Problem Description 给出n,m,p,求 (1^m + 2^m + 3^m + 4^m + ... + n^m) % p Input 第一行一个数T( <= 10),表示数据总数 然后每行给出3个数n,m,p(1 <= n <= m <= 10

ACDream - Lowbit Sum

先上题目: C - Lowbit Sum Time Limit: 2000/1000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others) SubmitStatus Problem Description long long ans = 0;for(int i = 1; i <= n; i ++)    ans += lowbit(i)lowbit(i)的意思是将i转化成二进制数之后,只保留最低位的1及其后面的0,截断前面的内容,然

ACdream: Sum

Sum Time Limit: 2000/1000MS (Java/Others)Memory Limit: 128000/64000KB (Java/Others) SubmitStatisticNext Problem Problem Description You are given an N*N digit matrix and you can get several horizontal or vertical digit strings from any position. For

ACdream 1431 Sum vs Product

题目链接:http://115.28.76.232/problem?pid=1431 Sum vs Product Time Limit: 4000/2000MS (Java/Others)Memory Limit: 128000/64000KB (Java/Others) SubmitStatisticNext Problem Problem Description Peter has just learned mathematics. He learned how to add, and h

HDU 1059 Dividing 分配(AC代码)多重背包的变形

1 #include <iostream> 2 using namespace std; 3 int num[6]; 4 int dp[200]; 5 bool divide(int sum) 6 { 7 int k,i,j; 8 for(i=0;i<6;i++) 9 for(k=0;k<num[i];k++) 10 for(j=sum;j>i;j--) 11 if(dp[j-(i+1)]+(i+1)>dp[j]) 12 dp[j]=dp[j-(i+1)]+(i+1);

【开源】ZXING的.NET版本源码解析

[概述] ZXing ("zebra crossing") is an open-source, multi-format 1D/2D barcode image processing library implemented in Java, with ports to other languages. 开源地址: https://github.com/zxing/zxing [工程结构] 以ZXing.Net.Source.0.14.0.0版本为例,此文件目录下对应两个工程: Bas

[Ramda] Compose and Curry

Curry: The idea of Curry is to spreate the data from the function. Using Curry to define the function logic and later pass the data into the function logic. Example1: const get = R.curry(function(prop, obj){ return obj[prop]; }); const obj1 = { foo:

uva714-复制书稿

题目链接 http://acm.hust.edu.cn/vjudge/problem/19689 解题思路 寻找最小上界用二分法 打印方案时从右边(尾)尽量往左边(头)划分.段数不够的话,从最左边往右一个一个划分. 代码 #include<stdio.h> #include<string.h> //#define LOCAL typedef long long ll; int div, n; ll book[505]; bool flag[505]; void Search(ll