洛谷 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;
}
转载请注明出处
https://www.cnblogs.com/xyr2005/