题意: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; }