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
每组数据一行,ansSample 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; }
相关文章推荐
- ACdreamOJ 1154 Lowbit Sum (数位dp)
- ACdream 1139(Sum-逆元)
- acdream 1431 Sum vs Product
- Sum vs Product(ACdream) —— dfs
- ACdreamOJ 1154 Lowbit Sum (数字dp)
- ACdream 1431 Sum vs Product
- ACDream - Sum
- 数位DP ACdream 1154 Lowbit Sum
- ACdream: Sum
- ACdream OJ 1154 Lowbit Sum
- acdream 1025 简单dp
- XMUT acdream 数据结构专场 C题(单调栈)
- ACdreamoj1110(多重背包)
- ACdream OJ 1099 瑶瑶的第K大
- 51nod 1305 Pairwise Sum and Divide
- 51nod 1305 Pairwise Sum and Divide
- Acdream Multiplication 基础题
- acdream 1015 Double Kings 树形结构 贪心
- 51nod 1305《Pairwise Sum and Divide》
- acdreamoj 1211 【有上下界限制的网络流】