题解 人生吧

传送门

看着比较可做,于是我反手一个莫比乌斯反演 T 成了 27pts

其实不需要反演
每个质因子及其幂次是独立的

\[ans=\prod\limits_p\prod\limits_i(p^i)^{\sum\limits_s[\gcd=p^i]} \]

\[ans=\prod\limits_p\prod\limits_ip^{\sum\limits_s[\gcd\geqslant p^i]} \]

\[ans=\prod\limits_p\prod\limits_ip^{2^{cnt_{p^i}}} \]

\(cnt_{p^i}\)\([l, r]\)\(p_i\) 作为因子出现的次数
格式以后再修吧

那么直接莫队+预处理质数幂次、逆元可以做到 \(O(n\sqrt n\log n)\)
发现 \(\leqslant \sqrt n\) 的质数和幂次的组合数量很少,可以前缀和处理
然后 \(>\sqrt n\) 的质数再莫队就可以做到 \(O(\sqrt n)\)
来不及写了,放个带 log 的跑路

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define pb push_back
#define ll long long
//#define int long long

char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
	int ans=0, f=1; char c=getchar();
	while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
	while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
	return ans*f;
}

int n, m;
int a[N];
const ll mod=998244353, mod2=mod-1;
inline int gcd(int a, int b) {return !b?a:gcd(b, a%b);}
inline ll qpow(ll a, ll b, ll mod=::mod) {ll ans=1; for (; b; a=a*a%mod,b>>=1) if (b&1) ans=ans*a%mod; return ans;}

namespace force{
	int sta[N], top;
	ll query(int l, int r) {
		ll ans=1; top=0;
		for (int i=l; i<=r; ++i) sta[top++]=a[i];
		int lim=1<<top;
		for (int s=1; s<lim; ++s) {
			bool flag=0;
			int tem=1;
			for (int i=0; i<top; ++i) if (s&(1<<i)) {
				if (!flag) tem=sta[i], flag=1;
				else tem=gcd(tem, sta[i]);
			}
			// cout<<"tem: "<<tem<<endl;
			ans=ans*tem%mod;
		}
		return ans;
	}
	void solve() {
		for (int i=1,l,r; i<=m; ++i) {
			l=read(); r=read();
			printf("%lld\n", query(l, r));
		}
	}
}

namespace task1{
	bool npri[N];
	vector<int> div[N];
	ll cnt[N], ans[N], now=1;
	int pri[N], mu[N], bel[N], pcnt, sqr;
	struct que{int l, r, id;}q[N];
	inline bool operator < (que a, que b) {return bel[a.l]==bel[b.l]?((bel[a.l]&1)?a.r<b.r:a.r>b.r):bel[a.l]<bel[b.l];}
	void add(int b) {
		for (auto& g:div[b]) {
			ll sum=0;
			for (auto& d:div[b/g])
				sum+=mu[d]*qpow(2, cnt[g*d], mod-1);
			now=now*qpow(g, (sum%mod2+mod2)%mod2)%mod;
		}
		for (auto& it:div[b]) ++cnt[it];
	}
	void del(int b) {
		for (auto& it:div[b]) --cnt[it];
		for (auto& g:div[b]) {
			ll sum=0;
			for (auto& d:div[b/g])
				sum+=mu[d]*qpow(2, cnt[g*d], mod-1);
			now=now*qpow(qpow(g, (sum%mod2+mod2)%mod2), mod-2)%mod;
		}
	}
	void solve() {
		sqr=sqrt(n);
		for (int i=1; i<=n; ++i) bel[i]=(i-1)/sqr+1;
		for (int i=1; i<=1e5; ++i)
			for (int j=i; j<=1e5; j+=i)
				div[j].pb(i);
		mu[1]=1;
		for (int i=2; i<=1e5; ++i) {
			if (!npri[i]) pri[++pcnt]=i, mu[i]=-1;
			for (int j=1,x; j<=pcnt&&i*pri[j]<=1e5; ++j) {
				npri[x=i*pri[j]]=1;
				if (!(i%pri[j])) break;
				else mu[x]=-mu[i];
			}
		}
		for (int i=1,l,r; i<=m; ++i) {
			l=read(); r=read();
			q[i]={l, r, i};
		}
		sort(q+1, q+m+1);
		for (int i=1,l=1,r=0; i<=m; ++i) {
			// cout<<"i: "<<i<<endl;
			while (l>q[i].l) add(a[--l]);
			while (r<q[i].r) add(a[++r]);
			while (l<q[i].l) del(a[l++]);
			while (r>q[i].r) del(a[r--]);
			ans[q[i].id]=now;
		}
		for (int i=1; i<=m; ++i) printf("%lld\n", ans[i]);
	}
}

namespace task2{
	bool npri[N];
	vector<int> div[N];
	int pri[N], mu[N], bel[N], pcnt, sqr;
	ll cnt[N], ans[N], rec[N], pw[N], now=1;
	struct que{int l, r, id;}q[N];
	inline bool operator < (que a, que b) {return bel[a.l]==bel[b.l]?((bel[a.l]&1)?a.r<b.r:a.r>b.r):bel[a.l]<bel[b.l];}
	void add(int b) {
		for (auto& g:div[b]) {
			ll sum=0;
			for (auto& d:div[b/g])
				sum+=mu[d]*pw[cnt[g*d]];
			now=now*qpow(g, (sum%mod2+mod2)%mod2)%mod;
		}
		for (auto& it:div[b]) ++cnt[it];
	}
	void del(int b) {
		for (auto& it:div[b]) --cnt[it];
		for (auto& g:div[b]) {
			ll sum=0;
			for (auto& d:div[b/g])
				sum+=mu[d]*pw[cnt[g*d]];
			now=now*qpow(qpow(g, (sum%mod2+mod2)%mod2), mod-2)%mod;
		}
	}
	void solve() {
		sqr=sqrt(n);
		for (int i=1; i<=n; ++i) bel[i]=(i-1)/sqr+1;
		for (int i=1; i<=1e5; ++i)
			for (int j=i; j<=1e5; j+=i)
				div[j].pb(i);
		// for (int i=1; i<=1e5; ++i) {
		// 	cout<<i<<": "; for (auto it:div[i]) cout<<it<<' '; cout<<endl;
		// } exit(0);
		mu[1]=1;
		for (int i=2; i<=1e5; ++i) {
			if (!npri[i]) pri[++pcnt]=i, mu[i]=-1;
			for (int j=1,x; j<=pcnt&&i*pri[j]<=1e5; ++j) {
				npri[x=i*pri[j]]=1;
				if (!(i%pri[j])) break;
				else mu[x]=-mu[i];
			}
		}
		pw[0]=1;
		for (int i=1; i<=1e5; ++i) pw[i]=pw[i-1]*2%(mod-1);
		for (int i=1,l,r; i<=m; ++i) {
			l=read(); r=read();
			q[i]={l, r, i};
		}
		sort(q+1, q+m+1);
		for (int i=1,l=1,r=0; i<=m; ++i) {
			// cout<<"i: "<<i<<' '<<l<<' '<<r<<endl;
			while (l>q[i].l) add(a[--l]);
			while (r<q[i].r) add(a[++r]);
			while (l<q[i].l) del(a[l++]);
			while (r>q[i].r) del(a[r--]);
			ans[q[i].id]=now;
		}
		for (int i=1; i<=m; ++i) printf("%lld\n", ans[i]);
	}
}

namespace task{
	bool npri[N];
	ll cnt[N], ans[N], now=1;
	vector<ll> pw[N], inv[N];
	int siz[N], pri[N], bel[N], low[N], lowp[N], pcnt, sqr;
	struct que{int l, r, id;}q[N];
	inline bool operator < (que a, que b) {return bel[a.l]==bel[b.l]?((bel[a.l]&1)?a.r<b.r:a.r>b.r):bel[a.l]<bel[b.l];}
	void add(int val) {
		for (int t=val; t>1; t/=low[t])
			for (int p=low[t]; p>1; p/=lowp[p])
				now=now*pw[lowp[p]][cnt[p]++]%mod;
	}
	void del(int val) {
		for (int t=val; t>1; t/=low[t])
			for (int p=low[t]; p>1; p/=lowp[p])
				now=now*inv[lowp[p]][--cnt[p]]%mod;
	}
	void solve() {
		sqr=sqrt(n);
		for (int i=1; i<=n; ++i) bel[i]=(i-1)/sqr+1;
		for (int i=2; i<=1e5; ++i) {
			if (!npri[i]) pri[++pcnt]=low[i]=lowp[i]=i;
			for (int j=1,x; j<=pcnt&&i*pri[j]<=1e5; ++j) {
				npri[x=i*pri[j]]=1;
				if (!(i%pri[j])) {low[x]=low[i]*pri[j]; lowp[x]=pri[j]; break;}
				else low[x]=lowp[x]=pri[j];
			}
		}
		for (int i=1; i<=n; ++i)
			for (int t=a[i]; t>1; t/=low[t])
				for (int p=low[t]; p>1; p/=lowp[p])
					++siz[p];
		for (int i=1; i<=1e5; ++i)
			for (int t=i; t>1; t/=low[t])
				for (int p=low[t]; p>1; p/=lowp[p])
					siz[lowp[p]]=max(siz[lowp[p]], siz[p]);
		for (int i=1; i<=1e5; ++i) if (!npri[i]) {
			pw[i].resize(siz[i]+5); inv[i].resize(siz[i]+5);
			for (int j=0; j<=siz[i]; ++j) pw[i][j]=qpow(i, qpow(2, j, mod-1));
			for (int j=0; j<=siz[i]; ++j) inv[i][j]=qpow(qpow(i, qpow(2, j, mod-1)), mod-2);
		}
		for (int i=1,l,r; i<=m; ++i) {
			l=read(); r=read();
			q[i]={l, r, i};
		}
		sort(q+1, q+m+1);
		for (int i=1,l=1,r=0; i<=m; ++i) {
			// cout<<"i: "<<i<<' '<<l<<' '<<r<<endl;
			while (l>q[i].l) add(a[--l]);
			while (r<q[i].r) add(a[++r]);
			while (l<q[i].l) del(a[l++]);
			while (r>q[i].r) del(a[r--]);
			ans[q[i].id]=now;
		}
		for (int i=1; i<=m; ++i) printf("%lld\n", ans[i]);
	}
}

signed main()
{
	freopen("C.in", "r", stdin);
	freopen("C.out", "w", stdout);

	n=read(); m=read();
	for (int i=1; i<=n; ++i) a[i]=read();
	// force::solve();
	task::solve();

	return 0;
}
posted @ 2022-04-10 21:30  Administrator-09  阅读(4)  评论(0编辑  收藏  举报