ACDream - Divide Sum
2014-07-31 23:45
295 查看
先上题目:
SubmitStatus
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= n; j ++)
ans += a[i] / a[j];
给出n,a[1]...a
,求ans
第一行n(1 <= n <= 10^5)
第二行n个数,a[1].. a
(1 <= a[i] <= 10^5)
/*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
,求ans
Input
不超过5组数据,每组数据:第一行n(1 <= n <= 10^5)
第二行n个数,a[1].. a
(1 <= a[i] <= 10^5)
Output
每组数据一行,ansSample 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。感觉暑假开始以后就一直很没有状态,敲一段代码都错漏百出,有的时候真的感觉没脸见人了(捂脸)。看来要快点加油才行啊。 上代码:
/* * this code is made by sineatos * Problem: 1181 * Verdict: Accepted * Submission Date: 2014-07-31 23:29:05 * Time: 428MS * Memory: 1868KB */ #include <cstdio> #include <cstring> #include <algorithm> #define lowbit(x) (x&(-x)) #define MAX 100002 #define ll long long using namespace std; int a[MAX]; int c[MAX]; int n; const int all=MAX-2; void add(int x,int e){ for(;x<=all;x+=lowbit(x)){ c[x]+=e; } } int sum(int x){ int ans=0; for(;x>0;x-=lowbit(x)) ans+=c[x]; return ans; } int main() { ll sum0,ans,lans; //freopen("data.txt","r",stdin); while(scanf("%d",&n)!=EOF){ memset(c,0,sizeof(c)); sum0=0; for(int i=0;i<n;i++){ scanf("%d",&a[i]); add(a[i],1); sum0+=a[i]; } sort(a,a+n); ans=0; lans=0; for(int i=0;i<n;i++){ if(a[i]==1){ ans+=sum0; }else if(i!=0 && a[i]==a[i-1]){ ans+=lans; }else{ int k,e=1; lans=0; for(int j=a[i];j<=a[n-1];j+=a[i]){ k=j+a[i]; if(k>a[n-1]) k=a[n-1]+1; int q=sum(k-1)-sum(j-1); lans+=(ll)q*e; e++; } ans+=lans; } } printf("%lld\n",ans); } return 0; }
/*Divide Sum*/
相关文章推荐
- acdream 1148 GCD SUM 莫比乌斯反演 ansx,ansy
- 51nod-1305 Pairwise Sum and Divide (规律)
- 51nod-【1305 Pairwise Sum and Divide】
- 51nod 1305 Pairwise Sum and Divide
- ACdream 1431 Sum vs Product
- ACdream 1154 Lowbit Sum (数位dp)
- 51NOD 1305 Pairwise Sum and Divide
- 【51Nod】1305 - Pairwise Sum and Divide(思维)
- leetcode_c++:Divide and Conquer:Count of Range Sum(327)
- ACdream 1431 Sum vs Product
- 51nod 1305 Pairwise Sum and Divide (数学)
- 51nod 1305 Pairwise Sum and Divide
- Pairwise Sum and Divide
- 51nod_1305 Pairwise Sum and Divide(数学规律)
- ACdream 1139(Sum-逆元)
- Pairwise Sum and Divide
- ACdream 1148 GCD SUM (久违的莫比乌斯)
- 51nod1305 Pairwise Sum and Divide
- 1305 Pairwise Sum and Divide
- ACdream 1156_LCP SUM