题目:
做法: 计算出来每个数的质因子在各个区间的贡献。
以第二组样例为例:
第一个元素的素因子2:
它能贡献的区间有[1,1],[1,2],……,[1,10] 10个区间
第一个元素的素因子3:
它能贡献的区间有[1,1],[1,2],……,[1,10] 10个区间
当前sum = 10+10
第二个元素的素因子7:
它能贡献的区间有[1,2],[1,3],……,[1,10] 9个区间
它能贡献的区间有[2,2],[2,3],……,[2,10] 9个区间
当前sum = 10+10 +9*2
同理第三个元素的素因子5算好后 sum = 10+10+9*2+8*3
当考虑第四元素的素因子5时,发现i = 3时的素因子5
在区间:
[1,3],[1,4],……,[1,10]
[2,3],[2,4],……,[2,10]
[3,3],[3,4],……,[3,10]
这3*8个区间中已经贡献过,所以我们从当前i = 4位置向后考虑 这个位置的素因子5对区间的贡献为 7
sum = 10+10+9*2+8*3+7
最终到n = 10,sum = 10+10+9*2+8*3+7+6*4+5*5+4+0+2*4+1+3=134
依次向后推理,我们现在每个素因子i贡献公式为:
a
n
s
i
=
(
n
−
p
r
i
m
e
[
i
]
[
p
o
s
]
+
1
)
∗
(
p
r
i
m
e
[
i
]
[
p
o
s
]
−
p
r
i
m
e
[
i
]
[
p
o
s
−
1
]
)
ans_i = (n-prime[i][pos]+1)*(prime[i][pos]-prime[i][pos-1])
ansi=(n−prime[i][pos]+1)∗(prime[i][pos]−prime[i][pos−1])
所以我们分解出质因子,把他们的位置放进vector, 扫一遍素数即可
代码
#include<bits/stdc++.h>
using namespace std;
#define IO ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define pb(x) push_back(x)
#define sz(x) (int)(x).size()
#define sc(x) scanf("%d",&x)
#define abs(x) ((x)<0 ? -(x) : x)
#define all(x) x.begin(),x.end()
#define mk(x,y) make_pair(x,y)
#define fin freopen("in.txt","r",stdin)
#define fout freopen("out.txt","w",stdout)
typedef long long ll;
const int mod = 1e9+7;
const double PI = 4*atan(1.0);
const int maxm = 1e8+5;
const int maxn = 1e6+5;
const int INF = 0x3f3f3f3f;
const ll LINF = 1ll<<62;
int a[maxn],n,tot;
int prime[maxn];
bool isprime[maxn];
vector<ll> vec[maxn];
void prime_table()
{
memset(isprime,true,sizeof(isprime));
isprime[0] = isprime[1] = false;
for(ll i=2;i<maxn;i++){
prime[tot++] = i;
if(isprime[i]){
for(ll j=i*i;j<maxn;j+=i)
isprime[j] = false;
}
}
}
void dec(int pos)
{
int t = a[pos];
for(int j=0;j<tot && prime[j]*prime[j]<=t;j++)
{
if(t%prime[j] == 0){
vec[prime[j]].pb(pos);
while(t%prime[j] == 0) t/=prime[j];
}
}
if(t>1) vec[t].pb(pos);
}
int main()
{
// fin;
IO;
prime_table();
cin>>n;
for(int i=2;i<maxn;i++) vec[i].pb(0);
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++) dec(i);
ll res = 0;
for(int i=0;i<tot;i++){
for(int j=1;j<sz(vec[prime[i]]);j++){
res = res+1ll*(vec[prime[i]][j] - vec[prime[i]][j-1])*1ll*(n-vec[prime[i]][j]+1);
}
}
cout<<res<<endl;
return 0;
}