【题解】CF594D REQ

Sol

挺套路的一个题。
首先 \(\phi(n) = n \times \prod (1-\frac{1}{p_i})\)
那么一次询问就变成了区间积乘上区间质因数并集的贡献。
前者直接前缀积维护即可。考虑后者怎么维护。
离线,把询问按右端点排序。依次加入 \(a_i\)
\(p\) 表示 \(a_i\) 的质因数。将 \(p\) 的贡献放在 \(i\) 这个位置上,若之前出现过 \(p\) 那么记个 \(last_p\) 表示上一次 \(p\) 出现的位置并删掉贡献。树状数组维护即可。
时间复杂度 \(O(n \log n \log a_i)\)

Code

//LYC_music yyds!
#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(0)
#define lowbit(x) (x&(-x))
#define int long long
using namespace std;
inline char gc()
{
	static char buf[1000000],*p1=buf,*p2=buf;
	return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
}
int read()
{
	int pos=1,num=0;
	char ch=getchar();
	while (!isdigit(ch))
	{
		if (ch=='-') pos=-1;
		ch=getchar();
	}
	while (isdigit(ch))
	{
		num=num*10+(int)(ch-'0');
		ch=getchar();
	}
	return pos*num;
}
void write(int x)
{
	if (x<0)
	{
		putchar('-');
		write(-x);
		return;
	}
	if (x>=10) write(x/10);
	putchar(x%10+'0');
}
void writesp(int x)
{
	write(x);
	putchar(' ');
}
void writeln(int x)
{
	write(x);
	putchar('\n');
}
const int N=1e6+10,mod=1e9+7;
struct node
{
	int l,r,id;
}q[N];
int n,s[N],a[N],c[N],last[N],p[N],ans[N],tot,vis[N],m;
inline int quickpower(int a,int b)
{
	int res=1;
	while (b)
	{
		if (b&1) (res*=a)%=mod;
		b>>=1; (a*=a)%=mod;
	}
	return res;
}
void init()
{
	for (int i=0;i<N;i++)
		c[i]=1;
	for (int i=2;i<N;i++)
	{
		if (!vis[i]) p[++tot]=i;
		for (int j=1;j<=tot&&i*p[j]<N;j++)
		{
			vis[i*p[j]]=1;
			if (i%p[j]==0) break;
		}
	}
}
inline void add(int x,int y)
{
	for (;x<N;x+=lowbit(x))
		c[x]=c[x]*y%mod;
}
inline int query(int x)
{
	int res=1;
	for (;x;x-=lowbit(x))
		res=res*c[x]%mod;
	return res;
}
void update(int x)
{
	int now=a[x];
	for (int i=1;p[i]*p[i]<=now;i++)
		if (now%p[i]==0)
		{
			assert(now%p[i]==0);
			add(x,(p[i]-1)*quickpower(p[i],mod-2)%mod);
			if (last[p[i]]) add(last[p[i]],p[i]*quickpower(p[i]-1,mod-2)%mod);
			last[p[i]]=x;
			while (now%p[i]==0) now/=p[i];
		}
	if (now!=1)
	{
		add(x,(now-1)*quickpower(now,mod-2)%mod);
		if (last[now]) add(last[now],now*quickpower(now-1,mod-2)%mod);
		last[now]=x;
	}
}
signed main()
{
	n=read(); s[0]=1; init();
	for (int i=1;i<=n;i++)
		a[i]=read(),s[i]=s[i-1]*a[i]%mod;
	m=read();
	for (int i=1;i<=m;i++)
		q[i]={read(),read(),i};
	sort(q+1,q+m+1,[](node x,node y)
	{
		return x.r<y.r;
	});
	int now=0;
	for (int i=1;i<=m;i++)
	{
		while (now<q[i].r) update(++now);
		// cout<<q[i].id<<' '<<s[q[i].r]*quickpower(s[q[i].l-1],mod-2)%mod<<' '<<query(q[i].r)*quickpower(query(q[i].l-1),mod-2)%mod<<'\n';
		ans[q[i].id]=s[q[i].r]*quickpower(s[q[i].l-1],mod-2)%mod*query(q[i].r)%mod*quickpower(query(q[i].l-1),mod-2)%mod;
	}
	for (int i=1;i<=m;i++)
		writeln(ans[i]);
}





posted @ 2022-07-22 10:01  dd_d  阅读(49)  评论(0)    收藏  举报