zoukankan      html  css  js  c++  java
  • 【bzoj4869】[Shoi2017]相逢是问候 线段树+扩展欧拉定理

    Description

    Informatikverbindetdichundmich.

    信息将你我连结。B君希望以维护一个长度为n的数组,这个数组的下标为从1到n的正整数。一共有m个操作,可以

    分为两种:0 l r表示将第l个到第r个数(al,al+1,...,ar)中的每一个数ai替换为c^ai,即c的ai次方,其中c是

    输入的一个常数,也就是执行赋值ai=c^ai1 l r求第l个到第r个数的和,也就是输出:sigma(ai),l<=i<=rai因为

    这个结果可能会很大,所以你只需要输出结果mod p的值即可。

    Input

    第一行有三个整数n,m,p,c,所有整数含义见问题描述。

    接下来一行n个整数,表示a数组的初始值。

    接下来m行,每行三个整数,其中第一个整数表示了操作的类型。

    如果是0的话,表示这是一个修改操作,操作的参数为l,r。

    如果是1的话,表示这是一个询问操作,操作的参数为l,r。

    1 ≤ n ≤ 50000, 1 ≤ m ≤ 50000, 1 ≤ p ≤ 100000000, 0 < c <p, 0 ≤ ai < p

    Output

    对于每个询问操作,输出一行,包括一个整数表示答案mod p的值。

    Sample Input

    4 4 7 2
    1 2 3 4
    0 1 4
    1 2 4
    0 1 4
    1 1 3

    Sample Output

    0
    3

    Sol

    根据扩展欧拉定理,参照bzoj3884,我们发现某个数字做一定次数比操作之后就不会变了,这个次数在(logn)左右,所以就可以用线段树维护区间和以及这个区间的数字有没有都处理完毕,然后直接维护即可。时间复杂度(nlog^3n),由于本题数据范围(50000),所以可以通过。

    注意细节:判断某个数字有没有超过(varphi(p)),以及(varphi(1)=varphi(2)=1),但是我们必须要在(p=1)的时候才能停止。

    Code

    #include <bits/stdc++.h>
    using namespace std;
    int n,m,P,c,K,op,l,r,a[50005],p[50005],V[50005],pr[50005],tot,sm[200005],mn[200005];
    int phi(int x)
    {
    	int res=x;
    	for(int i=1;pr[i]*pr[i]<=x;i++)
    	{
    		if(x%pr[i]) continue;
    		res-=res/pr[i];
    		while(x%pr[i]==0) x/=pr[i];
    	}
    	if(x>1) res-=res/x;return res;
    }
    void build(int x,int l,int r)
    {
    	if(l==r){scanf("%d",&a[l]);sm[x]=a[l]%P;mn[x]=0;return;}
    	int M=(l+r)>>1;build(x<<1,l,M);build(x<<1|1,M+1,r);
    	sm[x]=(sm[x<<1]+sm[x<<1|1])%P;mn[x]=min(mn[x<<1],mn[x<<1|1]);
    }
    int ksm(int a,int b,int P,bool &f)
    {
    	int res=1;bool gg=0;
    	for(;b;b>>=1,a=1ll*a*a%P)
    	{
    		if(b&1) f|=(gg|(1ll*res*a>=P)),res=1ll*res*a%P;
    		if(1ll*a*a>=P) gg=1;
    	}
    	return res;
    }
    int cal(int dep,int x)
    {
    	int res=x;if(res>=p[dep]) res=res%p[dep]+p[dep];
    	while(dep)
    	{
    		dep--;bool flag=0;
    		res=ksm(c,res,p[dep],flag);
    		if(flag) res+=p[dep];
    	}
    	return res%p[dep];
    }
    void upd(int x,int l,int r,int b,int e)
    {
    	if(mn[x]>=K) return;
    	if(l==r){mn[x]++;sm[x]=cal(mn[x],a[l]);return;}
    	int M=(l+r)>>1;
    	if(b<=M) upd(x*2,l,M,b,e);if(e>M) upd(x*2+1,M+1,r,b,e);
    	sm[x]=(sm[x<<1]+sm[x<<1|1])%P;mn[x]=min(mn[x<<1],mn[x<<1|1]);
    }
    int que(int x,int l,int r,int b,int e)
    {
    	if(b<=l&&r<=e) return sm[x];
    	int M=(l+r)>>1;
    	return ((b<=M?que(x*2,l,M,b,e):0)+(e>M?que(x*2+1,M+1,r,b,e):0))%P;
    }
    int main()
    {
    	for(int i=2;i<=50000;i++)
    	{
    		if(!V[i]) pr[++tot]=i;
    		for(int j=1;j<=tot&&i*pr[j]<=50000;j++){V[i*pr[j]]=1;if(i%pr[j]==0) break;}
    	}
    	scanf("%d%d%d%d",&n,&m,&P,&c);
    	p[0]=P;while(p[K]!=1){++K;p[K]=phi(p[K-1]);}p[++K]=1;
    	for(build(1,1,n);m--;)
    	{
    		scanf("%d%d%d",&op,&l,&r);
    		if(op==0) upd(1,1,n,l,r);
    		else printf("%d
    ",que(1,1,n,l,r));
    	}
    }
    
  • 相关阅读:
    HDU 1850 Being a Good Boy in Spring Festival
    UESTC 1080 空心矩阵
    HDU 2491 Priest John's Busiest Day
    UVALive 6181
    ZOJ 2674 Strange Limit
    UVA 12532 Interval Product
    UESTC 1237 质因子分解
    UESTC 1014 Shot
    xe5 android listbox的 TMetropolisUIListBoxItem
    xe5 android tts(Text To Speech)
  • 原文地址:https://www.cnblogs.com/CK6100LGEV2/p/9419411.html
Copyright © 2011-2022 走看看