P5624 [Celeste-A] Black Moonrise 題解

zifanwang發表於2024-03-30

考慮莫隊。

記數 \(i\) 的個數為 \(c_i\),套路地用莫比烏斯函式容斥,發現答案為 \(\sum_{i=1}^{10^5}\frac{c_i(c_i+1)}2\sum_{d|i}\mu(\frac i d)d\)

先預處理出前面的常數和每個數的因子,每次移動端點列舉因子更新答案即可。

因為數是隨機的,所以時間複雜度 \(\mathcal O(n\sqrt n \ln n)\)

參考程式碼:

#include<bits/stdc++.h>
#define ll long long
#define mxn 100003
#define pb push_back
#define rep(i,a,b) for(int i=a;i<=b;++i)
using namespace std;
struct node{
	int l,r,i;
}e[mxn];
int n,q,t,a[mxn],d[mxn],p[mxn],ps[mxn],c[mxn],mu[mxn];
ll ans,f[mxn],as[mxn];
vector<int>s[mxn];
void init(int n){
	mu[1]=1;
	rep(i,2,n){
		if(!d[i])d[i]=p[++t]=i,mu[i]=-1;
		rep(j,1,t){
			if(p[j]>d[i]||p[j]>n/i)break;
			d[p[j]*i]=p[j];
			mu[p[j]*i]=i%p[j]?-mu[i]:0;
		}
	}
	rep(i,1,n)for(int j=i;j<=n;j+=i){
		f[j]+=mu[j/i]*i;
		s[j].pb(i);
	}
}
inline void add(int x){
	for(int i:s[x]){
		c[i]++;
		ans+=(c[i]*2-1)*f[i];
	}
}
inline void del(int x){
	for(int i:s[x]){
		ans-=(c[i]*2-1)*f[i];
		c[i]--;
	}
}
signed main(){
	init(1e5);
	scanf("%d%d",&n,&q);
	const int b=sqrt(n);
	rep(i,1,n)scanf("%d",&a[i]),ps[i]=(i+b-1)/b;
	rep(i,1,q)scanf("%d%d",&e[i].l,&e[i].r),e[i].i=i;
	sort(e+1,e+q+1,[](node x,node y){
		return ps[x.l]!=ps[y.l]?x.l<y.l:ps[x.l]&1?x.r<y.r:x.r>y.r;
	});
	int l=1,r=0;
	rep(i,1,q){
		while(l>e[i].l)add(a[--l]);
		while(r<e[i].r)add(a[++r]);
		while(l<e[i].l)del(a[l++]);
		while(r>e[i].r)del(a[r--]);
		as[e[i].i]=ans;
	}
	rep(i,1,q)printf("%lld\n",as[i]);
	return 0;
}

相關文章