筛约数 T3 https://www.luogu.com.cn/problem/P2926
题面
今天是贝茜的生日,为了庆祝自己的生日,贝茜邀你来玩一个游戏。
贝茜让 () 头奶牛坐成一个圈。除了 号与 号奶牛外, 号奶牛与 号和 号奶牛相邻。 号奶牛与 号奶牛相邻。农夫约翰用很多纸条装满了一个桶,每一张包含了一个不一定是独一无二的 到 的数字。
接着每一头奶牛 从柄中取出一张纸条 。每头奶牛轮流走上一圈,同时拍打所有手上数字能整除在自己纸条上的数字的牛的头,然后做回到原来的位置。牛们希望你帮助他们确定,每一头奶牛需要拍打的牛。
输入格式
* Line 1: A single integer: N
* Lines 2..N+1: Line i+1 contains a single integer:
输出格式
* Lines 1..N: On line i, print a single integer that is the number of other cows patted by cow i.
样例 #1
样例输入 #1
5
2
1
2
3
4
样例输出 #1
2
0
2
1
3
提示
The 5 cows are given the numbers 2, 1, 2, 3, and 4, respectively.
The first cow pats the second and third cows; the second cows pats no cows; etc.
思路
大意是给 n 个数 , 对于第 个数 求出序列中其他能整除 的数的个数。
暴力求一个数的约数是 大概率会超时, 需要找个方法优化。
从约数出发逆向通过求其倍数来筛掉大数。
先把输入的数组统计每个数出现的次数 , 然后遍历区间 , 接着枚举 的倍数 。此时 就是 的约数, 让 即可。
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int a[N];
int cnt[N], ans[N];
void solve() {
int n;
cin >> n;
for(int i = 0; i < n; i++)
{
cin >> a[i];
cnt[a[i]]++;
}
for(int i = 1; i < N; i++)
{
for(int j = i; j < N; j += i)
ans[j] += cnt[i];
}
for(int i = 0; i < n; i++)
cout << ans[a[i]] - 1 << endl;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
solve();
return 0;
}