bzoj 5394: [Ynoi2016]炸脖龍 數論+樹狀數組

給一個長爲n的序列,m次操作,每次操作:
這裏寫圖片描述
Input
第一行兩個整數 n,m 表示序列長度和操作數
接下來一行,n個整數,表示這個序列
接下來m行,可能是以下兩種操作之一:
1 l r x 表示區間[l,r]加上 x
2 l r p 表示對區間[l,r]進行一次查詢,模數爲 p
n , m <= 500000 , 序列中每個數在 [2,1e9] 內,p <= 2e7, 每次加上的數在 [0,2e9]
共10組數據
Output
對於每個詢問,輸出一個數表示答案。

利用歐拉定理
這裏寫圖片描述
這裏不用求gcd,只需考慮gcd不爲1的情況,更通用
對一個數x取phi[x],最多幾次就取到1,所以可以暴力
區間修改用樹狀數組維護,每次暴力的時候查詢一下當前值。
注意特判 res 和 當前 p 的大小關係

///#pragma GCC optimize(3)
#include<bits/stdc++.h>
using namespace std;
#define maxn 500020
#define N 20000000
#define rep(i,l,r) for(register int i = l ; i <= r ; i++)
#define repd(i,r,l) for(register int i = r ; i >= l ; i--)
#define inf 1e8
#define lowbit(x) (x&(-x))


typedef long long ll;
inline int read(){
    register int num = 0;
    register char ch = getchar();
    while ( ch > '9' || ch < '0' ) ch = getchar();
    while ( ch <= '9' && ch >= '0' ) num = num * 10 + ch - '0' , ch = getchar();
    return num;
}
bool tag[N + 20];
int phi[N + 20],prime[N / 2],cnt;
ll add[maxn];
int n,m,a[maxn];

void init(){
    rep(i,2,N){
        if ( !tag[i] ) prime[++cnt] = i , phi[i] = i - 1;
        for (register int j = 1 ; j <= cnt && prime[j] * i <= N ; j++){
            tag[i * prime[j]] = 1;
            if ( (i % prime[j]) == 0 ){ phi[i * prime[j]] = phi[i] * prime[j]; break; }
            phi[i * prime[j]] = phi[i] * (prime[j] - 1);    
        }
    }
}
inline void modify(int id,int d){
    for (register int i = id ; i <= n ; i += lowbit(i)) add[i] += d;
}
inline ll query(int id){
    ll res = 0;
    for (register int i = id ; i ; i -= lowbit(i)) res += add[i];
    return res;
}
inline ll power(ll x,ll y,ll p){
    ll res = 1; int tag = 0,tagx = 0;
    while ( y ){
        if ( y & 1 ){
            res = res * x;
            tag |= tagx;
            if ( res >= p ) res %= p , tag = 1;
        }
        if ( x >= p ) tagx = 1 , x %= p;
        x = x * x;
        if ( x >= p ) tagx = 1 , x %= p;
        y >>= 1;
    }
    return res + (tag ? p : 0);
}
inline ll solve(int id,int r,ll p){
    if ( p == 1 ) return 1;
    if ( id > r ) return 1;
    ll cur = query(id) + a[id],y = solve(id + 1,r,phi[p]);
    return power(cur,y,p);
}   
int main(){
    //freopen("input.txt","r",stdin);
    init();
    scanf("%d %d",&n,&m);
    rep(i,1,n) a[i] = read();
    rep(i,1,m){
        int tp = read(),l = read(),r = read(),x = read();
        if ( tp == 1 ) modify(l,x) , modify(r + 1,-x);
        else{
            printf("%lld\n",solve(l,r,x) % x);
        }
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章