LOJ10199轻拍牛头
题目描述
原题来自:USACO 2008 Dec. Silver
今天是 Bessie 的生日,并且现在是聚会的游戏时间。Bessie 让编号为 1~N 的 N 头奶牛围成一个圈坐(所以除了最后一头牛,第 i 头奶牛与第 i-1 和 i+1 头奶牛相邻,第 N 头奶牛和第 N-1 头与第 1 头奶牛相邻)。同时,Farmer John 拿了个桶,在桶里装了十亿张小纸条,每张小纸条上写有某个范围在[1,10^6] 的整数。
接着,每头奶牛轮流从这个巨桶中抽取一个数 A_i(当然这些数没必要两两不同)。然后第 i 头奶牛走一圈,如果奶牛 i 手中的数字能够被奶牛 j (j<>i) 手中的数字整除,那么奶牛 i 会拍奶牛 j 的头。走完一圈后,奶牛i 回到原来的位置。
奶牛们想让你帮他们计算,对于每头奶牛,它需要拍多少头奶牛的头?
输入格式
第一行包含一个整数N ;
接下来第二到第 N+1 行每行包含一个整数 A_i。
输出格式
第一到第 N 行,第 i 行的输出表示第 i 头奶牛要拍打的牛数量。
样例
样例输入
5
2
1
2
3
4
样例输出
2
0
2
1
3
样例说明
第一头奶牛会拍第二、第三头奶牛,第二头牛不会拍任何奶牛的头,等等。
数据范围与提示
对于全部数据,1<=N<=10^5。
_____________________________________________________________
两两之间暴力枚举判断可以,但是n^2超时。
然后把每一个奶牛的的数值在10^6的范围内把它的倍数加1,这样就不用枚举n个数,复杂的为n*10^6/A_i,这样也可得到76分。
然后把所有的A_i排个序,相同的值的,同事修改而不是加1,这样就可以了。
_____________________________________________________________
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e5+10; 4 const int maxm=1e6+10; 5 int n; 6 int a[maxn],tj[maxm],aa[maxn]; 7 int b[maxn],jc[maxn]; 8 int main() 9 { 10 scanf("%d",&n); 11 for(int i=0;i<n;++i)scanf("%d",a+i),aa[i]=a[i]; 12 sort(a,a+n); 13 int ba=0,cnt=0; 14 for(int i=0;i<n;++i) 15 { 16 if(a[i]!=ba) 17 { 18 b[++cnt]=a[i]; 19 jc[cnt]++; 20 ba=a[i]; 21 } 22 else 23 jc[cnt]++; 24 } 25 for(int i=1;i<=cnt;++i) 26 { 27 for(int j=b[i];j<maxm;j+=b[i]) 28 tj[j]+=jc[i]; 29 } 30 for(int i=0;i<n;++i) 31 printf("%d\n",tj[aa[i]]-1); 32 return 0; 33 }