设有十个数字,其中下标为 3 3 3、 7 7 7、 10 10 10 (蓝色部分)的数字都有相同的质因子 x x x 。
那么,以 1 1 1 为左端点的所有区间中,有 8 8 8 个区间中包含质因子 x x x : [ 1 , 3 ] [1,3] [1,3]、 [ 1 , 4 ] [1,4] [1,4]、 [ 1 , 5 ] [1,5] [1,5]、 [ 1 , 6 ] [1,6] [1,6]、 [ 1 , 7 ] [1,7] [1,7]、 [ 1 , 8 ] [1,8] [1,8]、 [ 1 , 9 ] [1,9] [1,9]、 [ 1 , 10 ] [1,10] [1,10]。
同理,以 2 2 2、 3 3 3 为左端点的区间中,也各有 8 8 8 个区间包含质因子 x x x 。
依此类推,以 4 4 4、 5 5 5、 6 6 6、 7 7 7 为左端点的区间中,各有 4 4 4 个区间包含质因子 x x x 。以 8 8 8、 9 9 9、 10 10 10 为左端点的区间中,各有 1 1 1 个区间包含质因子 x x x 。
设一共有 n n n 个数,下标为 p p p 的数有质因子 x x x ,并且质因子 x x x 上一次出现是在下标 p r e [ x ] pre[x] pre[x]。那么,在以 ( p r e [ x ] , p ] (pre[x],p] (pre[x],p] 中任意一个下标为左端点的所有区间中,都有 ( n + 1 − p ) (n+1-p) (n+1−p) 个区间有质因子 x x x ,所以 a n s + = ( p − p r e [ x ] ) × ( n + 1 − p ) ans+=(p-pre[x])\times (n+1-p) ans+=(p−pre[x])×(n+1−p) 。
注意
- 先预处理出 [ 1 , 1 0 6 ] [1,10^6] [1,106] 中所有的质数,然后用这些质数进行质因数分解。
- 质因数分解的每一步都判断当前的数是否是质数,若是质数,直接停止分解。如果不这样做,一些大质数或大合数的分解都很慢。
- 记录答案时要用 l o n g l o n g long~long long long
- 使用
s
c
a
n
f
scanf
scanf ,
vjudge 上 cin 挺慢的。
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int n,t,v[N],prime[N],cnt,pre[N];
long long ans;
void getPrime(int n){
for(int i=2;i<=n;i++){
if(v[i]) continue;
prime[++cnt]=i;
for(int j=i;j<=n/i;j++) v[i*j]=1;
}
v[0]=v[1]=1;
}
void divide(int x,int p){
for(int i=1;prime[i]*prime[i]<=x;i++){
if(v[x]==0) break;
if(x%prime[i]==0){
while(x%prime[i]==0) x/=prime[i];
ans+=1LL*(n+1-p)*(p-pre[prime[i]]);
pre[prime[i]]=p;
}
}
if(x>1){
ans+=1LL*(n+1-p)*(p-pre[x]);
pre[x]=p;
}
}
signed main(){
getPrime(1e6);
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&t),divide(t,i);
printf("%lld\n",ans);
}