2018ICPC南京站Problem J. Prime Game

题意:

   对于所有数字分解质因子,如果某个质因子在这个区间出现,则贡献为1,求所有质因子对所有区间做的贡献。

解析:

  考虑如果所有全部区间都有这个质因子则这个质因子的贡献是n*(n+1)/2,对于任意因子,他的贡献等于区间个数减去他没有出现的区间个数,一个因子没有出现的区间就是出现的相邻两个位置之间。减去即可。

代码:

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <cstdio>
#include <queue>
#include <cmath>
#include <map>
#include <set>

using namespace std;

typedef long long ll;

const int maxn=1e6+10;

int prime[maxn];
ll a[maxn];

int pr[maxn];
void getprime(){
    memset(pr,0,sizeof(pr));
    for(int i=2;i<=maxn;i++){
        if(!pr[i])pr[++pr[0]]=i;
        for(int j=1;j<=pr[0]&&pr[j]<=maxn/i;j++){
            pr[pr[j]*i]=1;
            if(i%pr[j]==0)break;
        }
    }
}

int main(){
    int n;
    scanf("%d",&n);
    memset(prime,0,sizeof(prime));
    for(int i=1;i<=n;i++){
        scanf("%lld",&a[i]);
    }
    getprime();
    ll num=0;
    for(int i=1;i<=n;i++){

        for(int j=1;pr[j]<=a[i]/pr[j];j++){
            if(a[i]%pr[j]==0){
                while(a[i]%pr[j]==0){
                    a[i]=a[i]/pr[j];
                }
                ll x=i-prime[pr[j]]-1;

                num+=(x+1)*x/2;

                prime[pr[j]]=i;
            }
        }
        if(a[i]!=1){
            ll x=i-prime[a[i]]-1;

            num+=(x+1)*x/2;

            prime[a[i]]=i;
        }
    }
    ll ans=n;
    ans=ans*(ans+1)/2;
    ll nn=0;
    for(int i=2;i<maxn;i++){
        if(prime[i]){
            nn++;
            ll x=n-prime[i];

            num+=(x+1)*x/2;

            prime[i]=n+1;
        }
    }
    //printf("%lld....\n",nn);
    ans=ans*nn;
    printf("%lld\n",ans-num);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/wz-archer/p/11850757.html