原题链接
考察:约数
这题很久以前做过一次,但我没写博客,结果再来一次我还是不会(.)
错误思路:
倍数法求每个a[i]的倍数,基本代码如下:
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
for(int j=1;j<=M/a[i];j++)
sum[j*a[i]]++;
}
一旦数据出现大量1+1e6或者其他小的数,时间复杂度会退化到O(n、*m)还是十分恐怖
正确思路:
如果不能倍数法求约数就考虑试除法求约束,枚举每个数的约数时间复杂度是O(n\(\sqrt{m}\))只有108还是十分可观,我们只需要计数每个数字的次数即可.
Code
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 1e5+10;
int a[N],cnt[N*10],ans[N];
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
cnt[a[i]]++;
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=a[i]/j;j++)
{
if(a[i]%j==0) ans[i]+=cnt[j];
if(a[i]%j==0&&j!=a[i]/j) ans[i]+=cnt[a[i]/j];
}
printf("%d\n",ans[i]-1);
}
return 0;
}