洛谷P3949(樹狀數組+歐拉降冪)

題目:click
題意:在這裏插入圖片描述
題意簡單,題目毒瘤,我真的吐了,寫的線段樹最後一個點瘋狂T,改爲樹狀數組的區間更新,單點查詢(有不懂的可以參考:click)。加歐拉降冪,有些細節要對a進行處理。其他的見代碼。但是別人的線段樹沒有T。。。。。也給出代碼,大佬指點一下線段樹怎麼改。

#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<istream>
#include<vector>
#include<stack>
#include<set>
#include<map>
#include<algorithm>
#include<queue>
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3f
#define MAX_len 500005*4
using namespace std;
typedef long long ll;
typedef pair<int,int> PP;
long double eps=1e-9;
ll phi[20000005];
ll primes[20000005],pcnt=0;
bool vis[20000005];
inline void getPhi(int num)
{
    phi[1]=1;
    for(int i=2;i<=num;++i)
    {
        if(!vis[i])
        primes[++pcnt]=i,phi[i]=i-1;
        for(int j=1;j<=pcnt&&i*primes[j]<=num;++j)
        {
            vis[i*primes[j]]=1;
            if (!(i%primes[j]))
            {phi[i * primes[j]] = phi[i] * primes[j]; break;}
            phi[i * primes[j]] = phi[i] * (primes[j] - 1);
        }
    }
}
ll a[500010];
ll BIT[500010];
int NH;
inline ll lowbit(ll x)
{
    return x&(-x);
}
void add(int pos,ll val)
{
    for(;pos<=NH;pos+=lowbit(pos))
        BIT[pos]+=val;
}
ll query(ll pos)
{
    ll sum=0;
    for(;pos;pos-=lowbit(pos))
        sum+=BIT[pos];
    return sum;
}
inline ll MOD(ll n,ll mod)
{
    return n<mod?n:(n%mod+mod);
}
inline ll quickpow(ll a,ll n,ll mod)
{
    ll res=1;
    a=MOD(a,mod);//防爆long long 注意
    while(n)
    {
        if(n&1)
            res=MOD(a*res,mod);
        n>>=1;
        a=MOD(a*a,mod);
    }
    return res;
}
inline ll solve(int l,int r,ll mod)
{
    ll val=query(l)+a[l];
    if(l==r||mod==1)
        return MOD(val,mod);
    return quickpow(val,solve(l+1,r,phi[mod]),mod);
}
int main()
{
    memset(BIT,0,sizeof(BIT));
    getPhi(20000005);
    int m;
    scanf("%d %d",&NH,&m);
    for(int i=1;i<=NH;i++)
    {
        scanf("%lld",&a[i]);
    }
    while(m--)
    {
        int op,l,r;
        ll p;
        scanf("%d %d %d %lld",&op,&l,&r,&p);
        if(op==1)
        {
            add(l,p);
            if(r+1<=NH)
            add(r+1,-p);
        }
        else
        {
            printf("%lld\n",solve(l,r,p)%p);
        }
    }
    return 0;
}

T的代碼:

#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<istream>
#include<vector>
#include<stack>
#include<set>
#include<map>
#include<algorithm>
#include<queue>
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3f
#define MAX_len 500005*4
using namespace std;
typedef long long ll;
typedef pair<int,int> PP;
long double eps=1e-9;
ll phi[20000005];
ll primes[20000005],pcnt=0;
bool vis[20000005];
void getPhi(int num)
{
    phi[1]=1;
    for(int i=2;i<=num;++i)
    {
        if(!vis[i])
        primes[++pcnt]=i,phi[i]=i-1;
        for(int j=1;j<=pcnt&&i*primes[j]<=num;++j)
        {
            vis[i*primes[j]]=1;
            if (!(i%primes[j]))
            {phi[i * primes[j]] = phi[i] * primes[j]; break;}
            phi[i * primes[j]] = phi[i] * (primes[j] - 1);
        }
    }
}
struct A {
    int l,r;
    ll w,lazy;
}tree[MAX_len];
ll a[500010];
void build_tree(int p,int l1,int r1)
{
    tree[p].l=l1,tree[p].r=r1;
    tree[p].lazy=0;
    if(l1==r1)
    {
        tree[p].w=a[l1];
        return ;
    }
    int mid=(l1+r1)>>1;
    build_tree((p<<1),l1,mid);
    build_tree((p*2+1),mid+1,r1);
    tree[p].w=tree[(p<<1)].w+tree[(p<<1)|1].w;
}
void PushDown(int p)
{//下放標記
    if(tree[p].lazy>0)
    {
        ll temp=tree[p*2].r-tree[p*2].l+1;
        tree[p*2].w+=tree[p].lazy*temp;
        temp=tree[p*2+1].r-tree[p*2+1].l+1;
        tree[p*2+1].w+=tree[p].lazy*temp;
        tree[p*2].lazy+=tree[p].lazy;
        tree[p*2+1].lazy+=tree[p].lazy;
        tree[p].lazy=0;
    }
}
void update(int p,int l1,int r1,ll val)
{
    if(tree[p].l>=l1&&tree[p].r<=r1)
    {
        tree[p].w+=val*(tree[p].r-tree[p].l+1);
        tree[p].lazy+=val;
        return ;
    }
    PushDown(p);
    int mid=(tree[p].l+tree[p].r)/2;
    if(l1<=mid)
    {
        update(p*2,l1,r1,val);
    }
    if(r1>mid)
    {
        update(p*2+1,l1,r1,val);
    }
    tree[p].w=tree[p*2].w+tree[p*2+1].w;
}
ll query(int p,int l1,int r1)
{
    if(tree[p].l==tree[p].r)
    {
        return tree[p].w;
    }
    PushDown(p);
    int mid=(tree[p].l+tree[p].r)/2;
    ll res=0;
    if(l1<=mid)
    {
        res+=query(p*2,l1,r1);
    }
    if(r1>mid)
    {
        res+=query(p*2+1,l1,r1);
    }
    return res;
}
ll MOD(ll n,ll mod)
{
    return n<mod?n:(n%mod+mod);
}
ll quickpow(ll a,ll n,ll mod)
{
    ll res=1;
    a=MOD(a,mod);//防爆long long 注意
    while(n)
    {
        if(n&1)
            res=MOD(a*res,mod);
        n>>=1;
        a=MOD(a*a,mod);
    }
    return res;
}
ll solve(int l,int r,ll mod)
{
    ll val=query(1,l,l);
    if(l==r||mod==1)
        return MOD(val,mod);
    return quickpow(val,solve(l+1,r,phi[mod]),mod);
}
int main()
{
    getPhi(20000005);
    int n,m;
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
    }
    build_tree(1,1,n);
    while(m--)
    {
        int op,l,r;
        ll p;
        scanf("%d %d %d %lld",&op,&l,&r,&p);
        if(op==1)
        {
            update(1,l,r,p);
        }
        else
        {
            ll val=query(1,l,r);
            if(l==r)
            {
                printf("%lld\n",val%p);
                continue;
            }
            printf("%lld\n",solve(l,r,p)%p);
        }
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章