zoukankan      html  css  js  c++  java
  • 洛谷 P6217 简单数论题

    先推推式子

    [egin{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))

    [egin{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_iover g},{xover 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(nlog 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
    ",__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=='
    '||ch=='
    ') ch=getchar();
    	register char *tar=s;
    	*tar=ch,ch=getchar();
    	while(ch!=' '&&ch!='
    '&&ch!='
    '&&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
    ",ksm(ans[i])*res[i]%mod);
    	return 0;
    }
    
  • 相关阅读:
    [C++] split string by string
    工作三个月心得经验
    Ubuntu Command-Line: Enable Unlimited Scrolling in the Terminal
    What is the PPA and How to do with it ?
    WCF vs ASMX WebService
    The ShortCuts in the ADT (to be continued)
    when does the View.ondraw method get called
    Browsing Storage Resources with Server Explorer
    Get start with Android development
    C++ Frequently asking question
  • 原文地址:https://www.cnblogs.com/Frame233/p/12509551.html
Copyright © 2011-2022 走看看