洛谷 P6217 简单数论题

先推推式子

\[\begin{align*}Ans&=\prod_{i=l}^rlcm(a_i,x)\\&=\frac{x^{r-l+1}\prod_{i=l}^ra_i}{\prod_{i=l}^rgcd(a_i,x)}\end{align*} \]

\(x^{r-l+1}\prod_{i=l}^ra_i\) 可以通过简单预处理算出,下面只考虑 \(\prod_{i=l}^rgcd(a_i,x)\)

\[\begin{align*}\prod_{i=l}^rgcd(a_i,x)&=\prod_{g}g^{\sum_{i=l}^r[gcd(a_i,x)=g]}\\&=\prod_{g|x}g^{\sum_{i=l}^r[g|a_i]*[gcd({a_i\over g},{x\over g})=1]}\\&=\prod_{g|x}g^{\sum_{d|\frac xg} \mu(d)*\sum_{i=l}^r[dg|a_i]}\\设\ T=dg\\原式&=\prod_{T|x}(\prod_{g|T}g^{\mu(\frac Tg)})^{\sum_{i=l}^r[T|a_i]}\end{align*}\\ \]

对于 \(1<=T<=MAXV\) 预处理 \(val_T=\prod_{g|T}g^{\mu(\frac Tg)}\) ,这一部分是 \(O(n \log n)\) 的。

预处理每个数的因数。对于每个询问,枚举x的因数,将询问拆成 \(2*d(x)\) 个形如 \(val_T^{\sum_{i=1}^p[T|a_i]}\) 的乘积,挂在 r 和 l-1 位置的 vector 上。

\(a_i\) 按顺序加入,加入时枚举 \(a_i\) 的因子,询问时可以做到 \(O(1)\) 查询。

通过离线求逆元的方法精细地实现程序,可以做到 \(O(n\log n+\sum d(x))\)

// Author -- Frame

#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<iostream>

#define lowbit(x) ((x)&(-x))
#define Finline __inline__ __attribute__ ((always_inline))
#define DEBUG fprintf(stderr,"Running on Line %d in Function %s\n",__LINE__,__FUNCTION__)

typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;

const int inf=0x3f3f3f3f,Inf=0x7fffffff;
const ll INF=0x7fffffffffffffff;
const double eps=1e-10;

uint seed=19260817;
const uint _RAND_MAX_=4294967295u;
Finline uint Rand(){return seed=seed*998244353u+1000000007u;}

template <typename _Tp>_Tp gcd(const _Tp &a,const _Tp &b){return (!b)?a:gcd(b,a%b);}
template <typename _Tp>Finline _Tp abs(const _Tp &a){return a>=0?a:-a;}
template <typename _Tp>Finline _Tp max(const _Tp &a,const _Tp &b){return a<b?b:a;}
template <typename _Tp>Finline _Tp min(const _Tp &a,const _Tp &b){return a<b?a:b;}
template <typename _Tp>Finline void chmax(_Tp &a,const _Tp &b){(a<b)&&(a=b);}
template <typename _Tp>Finline void chmin(_Tp &a,const _Tp &b){(b<a)&&(a=b);}
template <typename _Tp>Finline bool _cmp(const _Tp &a,const _Tp &b){return abs(a-b)<=eps;}
template <typename _Tp>Finline void read(_Tp &x)
{
	register char ch(getchar());
	bool f(false);
	while(ch<48||ch>57) f|=ch==45,ch=getchar();
	x=ch&15,ch=getchar();
	while(ch>=48&&ch<=57) x=(((x<<2)+x)<<1)+(ch&15),ch=getchar();
	if(f) x=-x;
}
template <typename _Tp,typename... Args>Finline void read(_Tp &t,Args &...args)
{
	read(t);read(args...);
}
Finline int read_str(char *s)
{
	register char ch(getchar());
	while(ch==' '||ch=='\r'||ch=='\n') ch=getchar();
	register char *tar=s;
	*tar=ch,ch=getchar();
	while(ch!=' '&&ch!='\r'&&ch!='\n'&&ch!=EOF) *(++tar)=ch,ch=getchar();
	return tar-s+1;
}

const int N=200005;
const int mod=1000000007;
int p[N],pos;
bool pr[N];
int val[N];
int mu[N];
int inv[N];
std::vector<int> d[N];
ll ksm(ll a,int b=mod-2)
{
	ll res=1;
	while(b)
	{
		if(b&1) res=res*a%mod;
		a=a*a%mod,b>>=1;
	}
	return res;
}
void init()
{
	mu[1]=1;
	for(int i=2;i<N;++i)
	{
		if(!pr[i])
		{
			p[++pos]=i;
			mu[i]=-1;
		}
		for(int j=1;j<=pos&&i*p[j]<N;++j)
		{
			pr[i*p[j]]=true;
			if(!(i%p[j]))
			{
				mu[i*p[j]]=0;
				break;
			}
			mu[i*p[j]]=-mu[i];
		}
	}
	for(int i=1;i<N;++i) val[i]=1;
	inv[0]=inv[1]=1;
	for(int i=2;i<N;++i)
	{
		inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
	}
	for(int i=1;i<N;++i)
	{
		for(int j=i,t=1;j<N;j+=i,++t)
		{
			d[j].push_back(i);
			if(mu[t]==1) val[j]=1ll*val[j]*i%mod;
			else if(mu[t]==-1) val[j]=1ll*val[j]*inv[i]%mod;
		}
	}
}
int a[N];
struct node{
	int val;
	bool type;
	int id;
};
std::vector<node> _v[N];
int cnt[N];
int ans[N];
struct Node{
	int val,id;
}v[N<<5];
int _pos;
int mul[N<<5];
int res[N];
int _mul[N];
int main()
{
	init();
	int n,q;
	read(n,q);
	for(int i=1;i<N;++i) cnt[i]=1;
	_mul[0]=1;
	for(int i=1;i<=n;++i)
	{
		read(a[i]);
		_mul[i]=1ll*_mul[i-1]*a[i]%mod;
	}
	int l,r,x;
	for(int i=1;i<=q;++i)
	{
		read(l,r,x);
		res[i]=ksm(x,r-l+1)*_mul[r]%mod*ksm(_mul[l-1])%mod;
		ans[i]=1;
		for(auto it:d[x])
		{
			_v[r].push_back((node){it,1,i});
			_v[l-1].push_back((node){it,0,i});
		}
	}
	for(int i=1;i<=n;++i)
	{
		for(auto it:d[a[i]])
		{
			cnt[it]=1ll*cnt[it]*val[it]%mod;
		}
		for(auto it:_v[i])
		{
			if(it.type) ans[it.id]=1ll*ans[it.id]*cnt[it.val]%mod;
			else v[++_pos]=(Node){cnt[it.val],it.id};
		}
	}
	mul[0]=1;
	for(int i=1;i<=_pos;++i)
	{
		mul[i]=1ll*mul[i-1]*v[i].val%mod;
	}
	ll tmp=ksm(mul[_pos]);
	for(int i=_pos;i>=1;--i)
	{
		ans[v[i].id]=1ll*ans[v[i].id]*tmp%mod*mul[i-1]%mod;
		tmp=1ll*tmp*v[i].val%mod;
	}
	for(int i=1;i<=q;++i) printf("%lld\n",ksm(ans[i])*res[i]%mod);
	return 0;
}
posted @ 2020-03-17 11:31  xyr2005  阅读(247)  评论(1编辑  收藏  举报