【题解】CF594D REQ

Sol

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

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 @   dd_d  阅读(37)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示
主题色彩