zoukankan      html  css  js  c++  java
  • 【BZOJ4869】相逢是问候(线段树,欧拉定理)

    【BZOJ4869】相逢是问候(线段树,欧拉定理)

    题面

    BZOJ

    题解

    根据欧拉定理递归计算(类似上帝与集合的正确用法)
    所以我们可以用线段树维护区间最少的被更新的多少次
    如果超过了(varphi)的限制
    就不用再计算了
    如果需要计算就每次暴力算
    这样的复杂度(O(nlog^2))

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<vector>
    #include<queue>
    using namespace std;
    #define lson (now<<1)
    #define rson (now<<1|1)
    #define MAX 80000
    #define ll long long
    inline int read()
    {
    	int x=0,t=1;char ch=getchar();
    	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    	if(ch=='-')t=-1,ch=getchar();
    	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    	return x*t;
    }
    int a[MAX],C,P,n,m;
    ll phi[MAX],tot;
    ll Phi(ll x)
    {
    	ll ret=x;
    	for(ll i=2;i*i<=x;++i)
    		if(x%i==0)
    		{
    			ret=ret/i*(i-1);
    			while(x%i==0)x/=i;
    		}
    	if(x>1)ret=ret/x*(x-1);
    	return ret;
    }
    ll fpow(ll a,ll b,ll P)
    {
    	long long s=1;
    	bool fl=false,f2=false;
    	while(b)
    	{
    		if(b&1)s=1ll*s*a,fl|=f2;
    		if(s>=P)fl=true,s%=P;
    		a=a*a;
    		if(a>=P)f2=true,a%=P;
    		b>>=1;
    	}
    	if(fl)s+=P;
    	return s;
    }
    struct Node{long long sum;int tt;}t[MAX<<2];
    inline void Build(int now,int l,int r)
    {
    	if(l==r){t[now].sum=a[l]=read();return;}
    	int mid=(l+r)>>1;
    	Build(lson,l,mid);Build(rson,mid+1,r);
    	t[now].sum=(t[lson].sum+t[rson].sum)%P;
    }
    ll Calc(int l,int r,ll x,ll P)
    {
    	if(l==r)return fpow(x,1,P);
    	return fpow(C,Calc(l+1,r,x,phi[l+1]),P);
    }
    void Modify(int now,int l,int r,int L,int R)
    {
    	if(t[now].tt>=tot)return;
    	if(l==r)
    	{
    		t[now].sum=Calc(0,++t[now].tt,a[l],P)%P;
    		//t[now].sum=fpow(C,a[l],P)%P;
    		//a[l]=fpow(C,a[l],phi[1]);
    		return;
    	}
    	int mid=(l+r)>>1;
    	if(L<=mid)Modify(lson,l,mid,L,R);
    	if(R>mid)Modify(rson,mid+1,r,L,R);
    	t[now].tt=min(t[lson].tt,t[rson].tt);
    	t[now].sum=(t[lson].sum+t[rson].sum)%P;
    }
    int Query(int now,int l,int r,int L,int R)
    {
    	if(L<=l&&r<=R)return t[now].sum;
    	int mid=(l+r)>>1;ll ret=0;
    	if(L<=mid)ret=(ret+Query(lson,l,mid,L,R))%P;
    	if(R>mid)ret=(ret+Query(rson,mid+1,r,L,R))%P;
    	return ret;
    }
    int main()
    {
    	n=read();m=read();P=read();C=read();
    	Build(1,1,n);
    	phi[0]=P;
    	for(tot=1;;++tot)
    	{
    		phi[tot]=Phi(phi[tot-1]);
    		if(phi[tot]==1)break;
    	}
    	phi[++tot]=1;
    	while(m--)
    	{
    		int opt=read(),l=read(),r=read();
    		if(opt)printf("%d
    ",Query(1,1,n,l,r));
    		else Modify(1,1,n,l,r);
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    SCAU 12新生赛 H 拥挤的华农校巴
    C#实现让CPU占用率曲线听你的指挥 可指定运行核心
    追MM与设计模式的有趣见解
    FTP操作类
    怎么知道页面被放大缩小了
    SerialPort同步和异步数据读取
    Java Web 应用程序转换为 ASP.NET
    ASP.NET中进行消息处理(MSMQ)
    解压缩文件类
    怎样成为优秀的软件模型设计者?
  • 原文地址:https://www.cnblogs.com/cjyyb/p/8330169.html
Copyright © 2011-2022 走看看