--- title: "轻拍牛头" created: 2025-11-28 tags: - 算法 --- # 轻拍牛头 ## 题目 [轻拍牛头](https://www.cnblogs.com/VanHa0101/p/15979159.html) 今天是贝茜的生日,为了庆祝自己的生日,贝茜邀你来玩一个游戏. 贝茜让 N 头奶牛(编号 1 到 N)坐成一个圈。 除了 1 号与 N 号奶牛外,i 号奶牛与 i−1 号和 i+1 号奶牛相邻,N 号奶牛与 1 号奶牛相邻。 农夫约翰用很多纸条装满了一个桶,每一张纸条中包含一个 到 1000000 之间的数字。 接着每一头奶牛 从桶中取出一张纸条,纸条上的数字用 Ai 表示。 所有奶牛都选取完毕后,每头奶牛轮流走上一圈,当走到一头奶牛身旁时,如果**自己手中的数字能够被该奶牛手中的数字整除**,则拍打该牛的头。 牛们希望你帮助他们确定,每一头奶牛需要拍打的牛的数量。 输入格式 第一行包含整数 N。 接下来 N 行,每行包含一个整数 Ai。 输出格式 共 N 行,第 i 行的数字为第 i 头牛需要拍打的牛的数量。 数据范围 $1≤N≤10^5, 1≤Ai≤10^6$ 输入样例: 5 2 1 2 3 4 输出样例: 2 0 2 1 3 ## 思路分析 即共有 N 个整数 A1,A2,…,AN 对于每一个数 Ai,求其他的数中有多少个是它的约数。 直接写法是 把这些数都存起来 然后枚举每个数 再来一层枚举 判断除它外的每个数是否能被它整除 两层for循环 时间复杂度是O(n2)的,肯定会TLE ```cpp #include using namespace std; const int N=1e5+10; int cows[N],beat[N]; int n; int main() { cin>>n; for(int i=0;i>cows[i]; for(int i=0;i using namespace std; const int N = 1e5 + 10; // 数组大小限制 const int M = 1e6 + 10; // 数字的最大值限制 int cows[N]; // 存储每头奶牛手中的数字 int cnt[M]; // 统计每个数字出现的次数 int ans[M]; // 存储每个数字需要拍打的次数 int n; int main() { cin >> n; for (int i = 0; i < n; i++) { cin >> cows[i]; cnt[cows[i]]++; // 统计每个数字出现的次数 } // 对每个出现的数字,累加其倍数的约数数量 for (int i = 1; i < M; i++) { if (cnt[i]) { // 如果数字i出现过 for (int j = i; j < M; j += i) { ans[j] += cnt[i]; // 累加倍数的约数数量 } } } // 输出每头奶牛需要拍打的次数,不包括自己 for (int i = 0; i < n; i++) { cout << ans[cows[i]] - 1 << endl; } return 0; } ``` ## 同类题型 ## 视频讲解 --- ⬅️ [[试除法求约数|试除法求约数]] 🏠 [[00-刷题理模型]] ➡️ [[(可能要放在拓展欧几里得里)GCD|(可能要放在拓展欧几里得里)GCD]]