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.資訊將你我...