题目:
今天是贝茜的生日,为了庆祝自己的生日,贝茜邀你来玩一个游戏。贝茜让 N 头奶牛坐成一个圈。除了 1 号与 N号奶牛外,i 号奶牛与 i − 1 号和 i + 1 号奶牛相邻,N 号奶牛与 1 号奶牛相邻。农夫约翰用很多纸条装满了一个桶,每一张包含了一个 1 到 10^6 的数字。接着每一头奶牛 i 从桶中取出一张纸条 Ai ,每头奶牛轮流走一圈,同时拍打所有编号能整除在纸条上的数字的牛的头,然后走回到原来的位置。奶牛们想让你帮他们计算,对于每头奶牛,它需要拍多少头奶牛的头?
输入格式
第一行包含一个整数 N;
接下来第二到第 N + 1 行每行包含一个整数 Ai 。
输出格式
第一到第 N 行,第 i 行的输出表示第 i 头奶牛要拍打的牛数量。
样例
样例输入
5
2
1
2
3
4
样例输出
2
0
2
1
3
数据范围与提示
对于全部数据,1 ≤ N ≤ 10^5
思路:
此题主要是怎样快速求每个数的因子
这时候就用到唯一分解定理了,那么怎么用呢?
首先举个例子:72
72的因子:1 2 3 4 6 8 9 12 18 24 36 72
用唯一分解定理分解72之后得:2^3*3^2
即:2 2 2 3 3
质数为2组成:2 4 8
质数为3组成:3 9
用后面每个质数组的因子去乘以前面的因子放在数组后面即可
2 4 8
用3去乘得6 12 24把这些数放在数组后面并把3也放进去
然后用9去乘得18 36 72把这些数放在数组后面并把9也放进去
然后数组就变成 2 4 8 6 12 24 3 18 36 72
最后再把1放进去就OK了
AC代码:
#include<bits/stdc++.h> using namespace std; const int N=1000010; typedef long long ll; int book[N],a[N]; bool vis[N]; int x[N],y[N]; int tag[N],cnt; int fg[N]; void su()//素数打表So easy { cnt=0; vis[1]=true; for(int i=2;i<N;i++){ if(!vis[i]){ tag[cnt++]=i; for(int j=i*2;j<N;j+=i)vis[j]=true; } } } int main() { su(); int n; cin>>n; for(int i=1;i<=n;i++){ cin>>a[i]; book[a[i]]++;//把相同的数统计一下 } memset(fg,0,sizeof(fg)); for(int i=1;i<=n;i++){ if(fg[a[i]])continue;//计算过的数不用再算了 int k=a[i],z=0; for(int j=0;j<cnt&&tag[j]*tag[j]<=k;j++)//唯一分解定理 { if(k%tag[j]==0){ int t=0; int mi=tag[j]; while(k%tag[j]==0){ x[t++]=mi; k/=tag[j]; mi*=tag[j]; } if(z==0) { for(int w=0;w<t;w++) y[z++]=x[w]; } else { int q=z; for(int w=0;w<t;w++) { y[z++]=x[w]; for(int p=0;p<q;p++){ y[z++]=x[w]*y[p]; } } } } } if(k>1){ int q=z; y[z++]=k; for(int j=0;j<q;j++) y[z++]=y[j]*k; } y[z]=1; int sum=0; for(int j=0;j<=z;j++) if(y[j]==a[i])sum+=book[y[j]]-1; else sum+=book[y[j]]; fg[a[i]]=sum; } for(int i=1;i<=n;i++) printf("%d\n",fg[a[i]]); }