原题链接
考察:约数
这题很久以前做过一次,但我没写博客,结果再来一次我还是不会(.)
错误思路:
倍数法求每个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还是十分可观,我们只需要计数每个数字的次数即可.
#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; }