题目链接:http://acm.cist.bnu.edu.cn/contest/contest_problem_show.php?cpid=1777
如果一个整数a能够整除整数b,那么a叫做b的约数。
现在有N(1 <= N <= 100,000)个整数,对于其中的每一个数,请找出它在其余N - 1个整数中有多少个约数。
输入数据的第一行是一个整数N,以下N行每行有一个正整数,每个都不会超过1,000,000。
按输入顺序输出每个整数在其余N - 1个整数中的约数的个数,每个整数一行,总共输出N行。
5 2 1 2 3 4
2 0 2 1 3
先开始把题目看错了,以为是直接求n的约数个数,结果连样例都过不了。。。脸丢大了
这个题,题目时限很宽松,给了我们6秒,可谓时间充裕。
但是仍然不能采取O(n*m)的算法,因为这里n是10w,m是100w直接暴力肯定要超时。
我的方法是先开一个数组来记录每一个值出现的次数。
然后再通过枚举m的约数(这里只需要枚举到sqrt(m)就行了)来计算总次数。
这里时间复杂度变成了O(n*sqrt(m))在最坏的情况下,我们需要计算10w*sqrt(100w)=10w*1000=10^8
但是题目时限是6s而且这个已经是最坏的情况,所以是可以AC的
我的代码:
#include<stdio.h> #include<string.h> int hash[1000005]; int a[100005]; int main() { int i,j,n,ans; while(scanf("%d",&n)!=EOF) { memset(hash,0,sizeof(hash)); for(i=1;i<=n;i++) { scanf("%d",&a[i]); hash[a[i]]++; } for(i=1;i<=n;i++) { ans=0; for(j=1;j*j<=a[i];j++) { if(a[i]%j==0&&j*j!=a[i]) { ans=ans+hash[j]; ans=ans+hash[a[i]/j]; } if(j*j==a[i]) ans=ans+hash[j]; } if(ans) printf("%d\n",ans-1); else printf("%d\n",ans); } } return 0; }