一.题目链接
二.思路
三.代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
//cnt[i]:记录i出现了多少次 因为牛牛拿到的数字可能是一样的
//ans[i]:记录i是多少个数的倍数
int cnt[N], ans[N], a[N];
int n;
int main()
{
int maxn = 0;
cin >> n;
//输入每一头牛的数字
for(int i = 0; i < n; i ++)
{
cin >> a[i];
cnt[a[i]] ++;
//maxn = max(maxn, a[i]);
}
//枚举每一个数,虽然外层循环是10^6的,但是内层循环有些时候不会执行
for(int i = 0; i < N; i ++)
{
//如果cnt[i]!=0 说明出现了一个a[i];
if(!cnt[i]) continue;
//对于每一个a[i],将他的倍数都加上cnt[i];
for(int j = i ; j <= N; j += i)
ans[j] += cnt[i];
}
/*
枚举每一个a[i] 10^5。但是每次必然都会执行一次内循环。
for(int i = 0; i < n; i ++)
{
int t = a[i];
for(int j = t; j <= maxn; j += t)
ans[j] += 1;
}
*/
for(int i = 0; i < n; i ++) cout << ans[a[i]] - 1 << endl;
return 0;
}
四.总结
- 约数和倍数是很巧妙的相对关系,很多时候从约数的角度不好考虑可以从倍数的角度考虑。