2018南京区域赛——Problem J. Prime Game
Given a suqence of n integers ai
.
Let mul(l, r) = ∏r
i=l
ai and fac(l, r) be the number of distinct prime factors of mul(l, r).
Please calculate ∑ni=1∑nj=i fac(i, j)
Input
The first line contains one integer n (1 ≤ n ≤ 106) — the length of the sequence.
The second line contains n integers ai (1 ≤ i ≤ n, 1 ≤ ai ≤ 106) — the sequence.
Output
Print the answer to the equation.
Examples
standard input standard output
10
99 62 10 47 53 9 83 33 15 24
248
10
6 7 5 5 4 9 9 1 8 12
134
题意
给你一组数字,然后进行 ∑ni=1∑nj=i的遍历,对于每一个区间(i,j)得到i到j所有数的质因数的个数,然后把所有区间的质数个数相加就是答案。
思路
只要获得每个数的质因数,然后找到这个质因数上一次出现的位置,就可以算出这个数在答案中的贡献,通俗的来讲就是被几个区间包含了,需要用到几次。我们发现,对于每一个质因数的贡献就等于(pos[]数组存储的是这个质数上一次出现的位置,因为对于每一个质因数来说它只有当区间的左端点在上一个出现的相同数的后面,这个质因数才开始有贡献,计算公式为(i-pos[x])*(n-i+1)(pos[x]用来存上一次x的位置),注意取质因数的时候要进行优化,否则会超时。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn=1000007;
ll prime[maxn];
ll visit[maxn];
ll pos[1000007];
void Prime(){
for (ll i = 2;i <= maxn; i++) {
if (!visit[i]) {
prime[++prime[0]] = i;
}
for (ll j = 1; j <=prime[0] && i*prime[j] <= maxn; j++) {
visit[i*prime[j]] = 1;
if (i % prime[j] == 0) {
break;
}
}
}
}
int main()
{
Prime();
visit[1]=1;
ll n,ans=0;
scanf("%lld",&n);
for(ll i=1;i<=n;i++){
ll x;
scanf("%lld",&x);
for(int j=2;j*j<=x;j++)
{
if(x%j==0&&visit[j]==0)
{
ll ss=(i-pos[j])*(n-i+1);
ans+=ss;
pos[j]=i;
while(x%j==0)
{
x/=j;
}
}
int t=x/j;
if(x%j==0&&visit[t]==0&&x!=j*j)
{
ll ss=(i-pos[t])*(n-i+1);
ans+=ss;
pos[t]=i;
while(x%j==0)
{
x/=j;
}
}
}
if(visit[x]==0)
{
ll ss=(i-pos[x])*(n-i+1);
ans+=ss;
pos[x]=i;
}
}
printf("%lld\n",ans);
return 0;
}