• 洛谷 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/

  • 相关阅读:
    The Tamworth Two chapter 2.4
    USACO Controlling Companies chapter 2.3 已跪
    非递归快排
    链表二路归并
    Money Systems chapter 2.3 dp
    #pragma pack与sizeof union
    快慢指针
    12
    11
    10
  • 原文地址:https://www.cnblogs.com/xyr2005/p/12509551.html
Copyright © 2020-2023  润新知