描述
老师让n(1<=n<=100000)个小朋友围成一个圈,第k名同学和第k+1以及第k-1名同学相邻,1号同学和n号同学相邻,老师在一个包里放了很多写有数字的纸条,可能多个个纸条上的数字是相同的,并且数字num的范围是1<=num<=1000000。接下来每一位同学i从包里抽出一张纸条Ai,每位同学都走一圈,同时拍打能整除纸条上数字的同学后背,然后走回到自己的位置上。要求你计算出每位同学总共拍打了多少同学的后背。
输入
第一行包含一个整数n,接下来的n行,每行输入一个整数Ai。
输出
输出共有n行,每行一个数字,表示该同学拍打其他同学的数量。
输入样例 1
5 2 1 2 3 4
输出样例 1
2 0 2 1 3
思路:
详见注释(皮一下很开心)
代码:
#include<bits/stdc++.h> using namespace std; int a[10000005]; int n,mx=-100; int b[1000005]; int cnt[1000005]; void get_factor(){ for (int i = 1; i <= 1000000; i++){//题目中说明数字不超过100w if(!b[i]) continue;//数字必须存在,不存在则跳过 for (int j = 1; j <= 1000000 / i; j++){ // b[i*j]为真,表示i这个数字的j倍也是存在的,那么显然i*j能整除i, //所以我们要统计i*j这个数字能被整除多少次时就要把i这个数字出现的次数累加上去 //i这个数字出现的次数就是b[i] //我们用cnt[i*j] 来累计i*j这个数字被整除的次数,所以有cnt[i*j]+=b[i]; if(b[i*j]) cnt[i*j]+=b[i]; //这个地方很关键,因为j是从1开始的,所以要把自己整除自己的那一次减掉 //但是j初始化是必须从1而不能从2开始,因为i这个数字有可能出现了多次 //其实下面这一句可以不要,然后在输出答案的地方减1,及输出cnt[a[i]]-1就可以了。 if(i*j==i) cnt[i]--; } } } int main(){ scanf("%d",&n);//输入n个人 for(int i=1;i<=n;i++){ scanf("%d",&a[i]);//输入每个人手中的数字 b[a[i]]++;//因为每个人手中的数字可能重复,所以用桶算法 } get_factor(); for(int i=1;i<=n;i++) cout<<cnt[a[i]]<<endl; return 0; }
原文:https://www.cnblogs.com/mysh/p/11291551.html