luogu
loj維護乙個序列,支援區間求和,以及將區間內每乙個數 \(a_i\) 變成 \(c^\) (c為給定的常數), 並要求結果對 \(p\) 取模 ( \(p\) 不一定是質數 )
數列元素個數 \(n \leq 10^5\), 操作次數 \(m \leq 10^5\), \(1 \leq c < p \leq 10^8\)
注 : 以下稱 「將區間內每乙個數 \(a_i\) 變成 \(c^\)」 為 「操作」
一道看著就很線段樹的題目 ...
首先我們發現區間和似乎並不是那麼好維護:假定我們維護了 \(a_i\) 的區間和,但我們並不能很快的推出 \(c^\) 的區間和,因為從 \(a_i\) 到 \(c^\), 區間內的每乙個元素的變化幾乎完全沒有相關性,並不像區間加或區間和一樣能方便的維護。
但除了線段樹外,我們應該還會很自然的想到擴充套件尤拉定理
\[a^b \equiv a^ \pmod p, b \ge \varphi(p)
\]那麼很顯然的,當 \(a_i\) 對應的模數 \(\varphi(\varphi(\varphi(\varphi(...p)))) = 1\) 時,不論再怎麼操作 \(a_i\) 也不會變化了.
而對乙個數 \(p\) 不停地取 \(\varphi\) ,在取了 \(\log p\) 次後這個數必然會變成 \(1\).
那麼對於序列中所有的數,他們的總操作次數就應該不超過 \(n \log p\).
也就是說,對於每乙個區間操作,我們只需要操作其中沒有操作到 \(\log p\) 次的數, 其他的數可以不管他.
那顯然可以考慮預處理出每個數在前 \(\log p\) 次操作下分別會變成多少,操作時單點修改即可,複雜度就是 \(o(n\log n\log p)\).
這樣做還有個的好處:我們可以用樹狀陣列代替掉線段樹.
至於如何在區間操作中快速找到哪些數的操做次數小於 \(\log p\), 我們可以考慮使用逐漸變形成並查集的單向鍊錶(我自己瞎扯的名字),具體而言就是,我們有乙個 \(next\) 陣列, \(next_i\) 表示下標大於等於 i 的數中第乙個操作次數小於 \(\log p\) 的數 (即繼續操作可能會改變量值的數) 的下標,並有乙個 \(time\) 陣列記錄每個數當前的操作次數.
顯然初始時 \(next_i = i + 1\).
那麼查詢下標大於等於 i 的第乙個操作次數小於 \(\log p\) 的數可以這樣實現:
int get(int i)
這應該比較直觀的體現了他為什麼是"逐漸變形成並查集的單向鍊錶"......
#include #define lowbit(x) x&-x
using namespace std;
typedef long long ll;
const int n = 50010;
const int lam = 10;
ll n, m, p, c, logcp, top, nxt[n], tree[n], a[n], tms[n], phi[n], val[lam + 10][n];
inline int read()
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}ll ksm(ll x, ll p)
int get_phi(int x) //暴力求尤拉函式
}return (x == 1) ? res : res * (x - 1);
}int dfs(int x, int num, int t)//深搜擴充套件尤拉定理
void prework()//預處理出a[i]操作b次後會變成多少,即val[b][i]
for(int j = 1; j <= n; j++)
}}void add(int pos, int val)
ll que(int pos)
int get(int now)
int main()}}
return 0;
}
順便一提,雖然說理論上每個數需要操作 \(\log p\) 次才不會變化,但這題資料比較水,每個數操作 5 次就可以不管他了.
還有就是一定要注意擴充套件尤拉定理需要滿足指數不小於 \(\varphi(p)\).
六省聯考2017 相逢是問候 題解
安利 雜題選做 洛谷 p3747 六省聯考2017 相逢是問候 首先可以想到通過尤拉定理計算 不難發現只有前 log 次修改是有用的 那麼直接維護就可以了 注意不要每次計算的時候直接呼叫快速冪 這樣會多乙個 log.正確的姿勢是對於每個 mod o sqrt 預處理一下 c x 和 c 然後就可以做...
六省聯考2017 相逢是問候
題意 給定乙個長度為n的序列a,常數p和c。你需要支援m次操作,分為兩種 n,m leq 50000,c題解 一般像這種看起來根本沒法維護的線段樹題都是操作幾次就變常數了,於是我們考慮一下這個操作的性質。首先引入拓展尤拉定理 a mod p begina b 注意到 phi p 在 k 30 左右的...
SHOI 2017 相逢是問候
loj 2142 相逢是問候 首先 這道題目很輕易地就能想到用線段樹求和 但是題目的難點在於 ca imodp caimod pmodp 解決這個問題的公式是 ab abmod p b ai p modp 根據這個公式逆推一下 ca imodp caimod p ai p p modp 以下簡寫 b...