bzoj4869 Shoi2017 相逢是問候

2022-05-01 06:21:08 字數 2752 閱讀 6689

time limit: 40 sec  memory limit: 512 mb

submit: 1311  solved: 470

[submit][status][discuss]

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的值即可。

第一行有三個整數n,m,p,c,所有整數含義見問題描述。

接下來一行n個整數,表示a陣列的初始值。

接下來m行,每行三個整數,其中第乙個整數表示了操作的型別。

如果是0的話,表示這是乙個修改操作,操作的引數為l,r。

如果是1的話,表示這是乙個詢問操作,操作的引數為l,r。

1 ≤ n ≤ 50000, 1 ≤ m ≤ 50000, 1 ≤ p ≤ 100000000, 0 < c 對於每個詢問操作,輸出一行,包括乙個整數表示答案mod p的值。

4 4 7 2

1 2 3 4

0 1 4

1 2 4

0 1 4

1 1 30 3

鳴謝多名網友提供正確資料,已重測!

黑吉遼滬冀晉六省聯考&&鳴謝xlk授權本oj使用權

分析:比較難的一道題.

如果做過bzoj3884,就會想到用尤拉定理來降冪.  和區間開根號一樣,乙個數操作有限次數後就會變成乙個常數. 在它變成常數以前對它暴力修改即可. 為什麼會變成乙個常數呢? p --> phi(p) --> phi(phi(p)) ...... 最後一定會變成1. 不論什麼數mod 1都等於0.

區間開根號可以用分塊來做,那麼這道題能不能用分塊來做呢?顯然是不行的,複雜度太高! 每個數會被暴力修改log次,每次修改需要對log個phi求快速冪,快速冪的複雜度也是log的,也就是說:將乙個數修改到底的複雜度是o(log^3n)的,顯然是不能接受的. 既然不能分塊,用線段樹做就好了.

令p通過不斷取phi變成1的次數為cnt. 如果要修改乙個區間[l,r],若當前區間的所有元素的最少操作次數≥cnt,這個區間的元素就不需要被修改了. 否則暴力修改.

一開始將每一層的phi給記錄下來(模數). 如果要修改第i個元素,第i個元素已經被修改tot次了,那麼就從第tot + 1層到1層逐層計算答案.  需要注意的是:擴充套件尤拉定理只能在冪次≥phi的時候才能使用,在快速冪的時候判斷一下就好了.

注意:一定要展開phi(1) = 1那一層. p=3,c=2的話,整個序列只有乙個數字,一開始是0,接著不斷進行修改操作和查詢操作。

錯誤的**,會返回0->1->2->2->2->.... (p=3,c=2),但是事實上應該是0->1->2->1->1->....

#include #include 

#include

#include

#include

using

namespace

std;

typedef

long

long

ll;const ll maxn = 50010

;ll n,m,p,c,a[maxn],p[maxn],cnt,sum[maxn

<< 2],minn[maxn << 2

];ll phi(ll x)

}if (x > 1

) res = res / x * (x - 1

);

return

res;

}void

pre()

p[++cnt] = 1;}

void

pushup(ll o)

void

build(ll o,ll l,ll r)

ll mid = (l + r) >> 1

; build(o * 2

,l,mid);

build(o * 2 + 1,mid + 1

,r);

pushup(o);

}ll qpow(ll a,ll b,ll pp,

bool &flag)

if (b != 1 && a * a >=pp)

flag = true

; a = (a * a) %pp;

b >>= 1

; }

return

res;

}ll calc(ll x,ll ph)

//cout << res << endl;

return res % p[0];}

void

update(ll o,ll l,ll r,ll x,ll y)

ll mid = (l + r) >> 1

;

if (x <=mid)

update(o * 2

,l,mid,x,y);

if (y >mid)

update(o * 2 + 1,mid + 1

,r,x,y);

pushup(o);

}ll query(ll o,ll l,ll r,ll x,ll y)

intmain()

return0;

}

BZOJ4869 Shoi2017 相逢是問候

維護乙個長度為n的陣列,m個操作,支援兩種操作 0 l r表示將第l個到第r個數中的每乙個數ai替換為c ai 1 l r求第l個到第r個數的和。首先要知道擴充套件尤拉定理 如果a ph i p ca c am odph i p ph i p modp a phi p c equiv c mod p...

Bzoj3562 神器化合物 Shoi 2014

ac通道 分析 若把每乙個原子看作乙個節點,將化學鍵看作一條邊,那麼這個題目要求的 分子的個數 很容易就可以看出是求圖中聯通塊的個數。求聯通塊的個數,可以使用並查集。可如何求出每一步的聯通塊的個數呢?可以知道,當連上一條邊時,若此邊連線的是兩個不同的聯通塊,那麼分子個數就會減一 當刪去一條邊時,若刪...

4869 Shoi2017 相逢是問候

4869 shoi2017 相逢是問候 time limit 40 sec memory limit 512 mb submit 440 solved 124 submit status discuss description informatikverbindetdichundmich.資訊將你我...