码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2018-01-22 19:32:01      阅读:190      评论:0      收藏:0      [点我收藏+]

标签:oid   har   include   递归   复杂度   ace   bre   欧拉   amp   

【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\n",Query(1,1,n,l,r));
        else Modify(1,1,n,l,r);
    }
    return 0;
}

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

标签:oid   har   include   递归   复杂度   ace   bre   欧拉   amp   

原文地址:https://www.cnblogs.com/cjyyb/p/8330169.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!