Gym - 101981J The 2018 ICPC Asia Nanjing Regional Contest J.Prime Game 计数

题面

题意:1e6的数组(1<a[i]<1e6),     mul (l,r) =l × (l+1) ×...× r,  fac(l,r) 代表 mul(l,r) 中不同素因子的个数,求sigma(i=1 to n) sigma(j=i to n) fac(i,j)

题解:计数套路题,算贡献,直接算有多少区间包含某一个素数的倍数

记录一下所有2的倍数的位置,3的倍数的位置,

    之后算有多少个区间包含2倍数的位置,这个就是2这个素数的倍数的贡献,

    然后算有多少个区间包含3这个素数的倍数的位置,这个就是3这个素数的贡献。

#include<bits/stdc++.h>
using namespace std;
#define mem(a,i) memset(a,i,sizeof(a))
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define pb push_back
typedef long long ll;
const int maxn=1e6+5;
int a[maxn],n;
bool vis[1005];
int prim[1005];
vector<int> vec[maxn];
int cnt;
void init() {
    mem(vis,0);
    rep(i,0,maxn-1) vec[i].clear();
    cnt=0;
    rep(i,2,1004) {
        if(!vis[i]) {
            prim[++cnt]=i;
            for(int j=i*2;j<1005;j+=i) {
                vis[j]=1;
            }
        }
    }
}
int main() {
    init();
    scanf("%d",&n);
    rep(i,1,n) {
        scanf("%d",&a[i]);
        int temp=a[i];
        rep(j,1,cnt) {
            if(temp<prim[j]) break;
            if(temp%prim[j]==0) {
                vec[prim[j]].pb(i);
                while(temp%prim[j]==0) temp/=prim[j];
            }
        }
        if(temp!=1) vec[temp].pb(i);
    }
    ll ans=0;
    rep(i,2,maxn-1) {
        ll res=1ll*n*(n+1)/2;
        int len=vec[i].size();
        if(len==0) continue;
        rep(j,0,len-1) {
            if(j==0) res-=1ll*(vec[i][j]-1)*(vec[i][j])/2;
            if(j==len-1) res-=1ll*(n-vec[i][j])*(n-vec[i][j]+1)/2;
            if(j+1<len) res-=1ll*(vec[i][j+1]-vec[i][j])*(vec[i][j+1]-vec[i][j]-1)/2;
        }
        ans+=res;
    }
    printf("%lld\n",ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/qywhy/p/10102426.html
今日推荐