zoukankan      html  css  js  c++  java
  • 题解 CF1109E 【Sasha and a Very Easy Test】

    (Large exttt{CF1109E})

    前置知识:欧拉定理(扩展费马小定理),基本线段树操作

    题意

    十分简洁,不多赘述。

    注意 (mod) 可以不为质数,每个单点除操作保证能整除。

    思路

    (mod) 是质数就好做了(不然怎么会是黑题),但 (mod) 不是质数代表在单点除时不能直接用费马小定理边乘边模。

    可以考虑使用扩展费马定理:

    [a^{varphi(p)}=1mod p ~~(gcd(a,p)=1) ]

    发现小于 (1e9) 的每个数质因数个数不会超过 (9) 个,可以想到将所有要进行操作的数分成两部分,一部分质因子全是 (mod) 的质因子,开一个大小为 (10) 的数组暴力操作,若除就在这个数组里面减去要减的质因子,剩下部分的肯定与 (mod) 互质,除一个数就乘 (x^{varphi(mod)-1}) 并取模就好了。

    注意细节,可以参考代码。

    另附上 (varphi(n)) 的求法:

    [varphi(n)=n imesprod^{x}_{i=1}frac{p_i}{p_i-1} ]

    不要像我 (varphi) 求错了调1h

    时间复杂度 ( exttt{O(10NlogN)}) (远远达不到这个上限)。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    
     #define ls n << 1
     #define rs n << 1 | 1
     #define int long long
     const int N = 1e5;
    inline int read()
    {
        int s = 0;
        register bool neg = 0;
        register char c = getchar();
        for (; c < '0' || c > '9'; c = getchar())
            neg |= (c == '-');
        for (; c >= '0' && c <= '9'; s = s * 10 + (c ^ 48), c = getchar())
            ;
        s = (neg ? -s : s);
        return s;
    }
    
    int a,mod,b,p[10],top,q[N+10],t[N+10][10],add[10],pp;
    struct segment {
    	int l,r,val,lazy1[10],lazy2,lazy3;
    } s[N*4+10];
    
    inline int get_phi(int n) {
    	int ans = n;
    	for (int i = 2; i*i <= n; i++) {
    		if (!(n%i)) {
    			ans = 1ll * ans * (i - 1) / i;
    			while (!(n%i))n /= i;
    		}
    	}
    	if (n > 1)ans = 1ll * ans * (n - 1) / n;
    	return ans;
    }
    
    inline void get(int n) {
    	int qq=sqrt(n);
    	for(int i=2;i<=qq;i++) {
    		if(n%i==0) {
    			p[++top]=i;
    			while(n%i==0) n/=i;
    		}
    	}
    	if(n!=1) p[++top]=n;
    }
    
    inline int qpow(int n,int m) {
    	int res=1;
    	for(;m;m>>=1) {
    		if(m&1) res=res*n%mod;
    		n=n*n%mod;
    	}
    	return res;
    }
    
    inline int calc(int n) {
    	int res=1;
    	for(int i=1;i<=top;i++) res=(res*qpow(p[i],t[n][i]))%mod;
    	return res;
    }
    
    inline void up(int n) {
    	s[n].val=(s[ls].val+s[rs].val)%mod;
    }
    
    inline void down(int n) {
    	s[ls].val=s[ls].val*s[n].lazy2%mod;
    	s[rs].val=s[rs].val*s[n].lazy2%mod;
    	s[ls].lazy2=s[ls].lazy2*s[n].lazy2%mod;
    	s[rs].lazy2=s[rs].lazy2*s[n].lazy2%mod;
    	s[ls].lazy3=s[ls].lazy3*s[n].lazy3%mod;
    	s[rs].lazy3=s[rs].lazy3*s[n].lazy3%mod;
    	s[n].lazy2=s[n].lazy3=1;
    	for(int i=1;i<=top;i++) {
    		s[ls].lazy1[i]+=s[n].lazy1[i];
    		s[rs].lazy1[i]+=s[n].lazy1[i];
    		s[n].lazy1[i]=0;
    	}
    	return;
    }
    
    inline void build(int n,int l,int r) {
    	s[n].l=l;
    	s[n].r=r;
    	s[n].lazy2=s[n].lazy3=1;
    	memset(s[n].lazy1,0,sizeof(s[n].lazy1));
    	if(l==r) {
    		s[n].val=q[l]*calc(l)%mod;
    		return;
    	}
    	int mid=(l+r)>>1;
    	build(ls,l,mid);
    	build(rs,mid+1,r);
    	up(n);
    }
    
    inline void div(int n,int m,int k) {
    	if(s[n].l==s[n].r) {
    		q[m]=q[m]*s[n].lazy3%mod;
    		s[n].lazy3=1;
    		for(int i=1;i<=top;i++) {
    			t[m][i]+=s[n].lazy1[i];
    			s[n].lazy1[i]=0;
    			while(k%p[i]==0) t[m][i]--,k/=p[i];
    		}
    		q[m]=q[m]*qpow(k,pp-1)%mod;
    		s[n].val=q[m]*calc(m)%mod;
    		return;
    	}
    	down(n);
    	int mid=(s[n].l+s[n].r)>>1;
    	if(m<=mid) div(ls,m,k);
    	else div(rs,m,k);
    	up(n);
    }
    
    inline void times(int n,int l,int r,int k,int _k) {
    	if(s[n].l>=l&&s[n].r<=r) {
    		s[n].val=s[n].val*k%mod;
    		s[n].lazy2=s[n].lazy2*k%mod;
    		s[n].lazy3=s[n].lazy3*_k%mod;
    		for(int i=1;i<=top;i++) s[n].lazy1[i]+=add[i];
    		return;
    	}
    	down(n);
    	int mid=(s[n].l+s[n].r)>>1;
    	if(l<=mid) times(ls,l,r,k,_k);
    	if(mid<r) times(rs,l,r,k,_k);
    	up(n);
    }
    
    inline int query(int n,int l,int r) {
    	if(s[n].l>=l&&s[n].r<=r) return s[n].val;
    	down(n);
    	int mid=(s[n].l+s[n].r)>>1,res=0;
    	if(l<=mid) res=(res+query(ls,l,r))%mod;
    	if(mid<r) res=(res+query(rs,l,r))%mod;
    	return res;
    }
    
    signed main()
    {
    //	freopen("in.txt","r",stdin);
    	a=read();
    	mod=read();
    	pp=get_phi(mod);
    	int opt,x,y,z;
    	get(mod);
    	for(int i=1;i<=a;i++) {
    		q[i]=read();
    		for(int j=1;j<=top;j++) {
    			while(q[i]%p[j]==0) {
    				q[i]/=p[j];
    				t[i][j]++;
    			}
    		}
    	}
    	build(1,1,a);
    	b=read();
    	for(int i=1;i<=b;i++) {
    		opt=read();
    		x=read();
    		y=read();
    		if(opt==1) {
    			z=read();
    			if(z==1) continue;
    			int _z=z;
    			for(int j=1;j<=top;j++) {
    				add[j]=0;
    				while(_z%p[j]==0) _z/=p[j],add[j]++;
    			}
    			times(1,x,y,z,_z);
    		}
    		else if(opt==2) div(1,x,y);
    		else printf("%lld
    ",query(1,x,y));
    	}
        return 0;
    }
    
  • 相关阅读:
    一个程序媛小渣的自我反省--纯属吐槽
    前端常见的性能优化手段
    js的命名空间 && 单体模式 && 变量深拷贝和浅拷贝 && 页面弹窗设计
    js-signals学习以及应用
    WebGL和ThreeJs学习6--射线法确定3D空间中所选物体
    前端之js-本地存储-localStorage && IndexedDB
    HelloStruts
    实验三 敏捷开发与XP实验 20175301李锦然实验报告
    《Java》第九周学习总结
    MYCP作业
  • 原文地址:https://www.cnblogs.com/RedreamMer/p/14068198.html
Copyright © 2011-2022 走看看