【做題】agc006C - Rabbit Exercise——模型轉換
阿新 • • 發佈:2018-10-05
block arr 個性 特殊 但我 pla 所有 時間 %d 。
和\(p'_{i-1}\)。因此,這\(m\)個操作就是對\(p'\)做一個置換。我們把每個環摳出來就能得到重復做\(k\)次置換之後的結果。最好再通過\(p'\)還原出\(p\)就好了。
題意:數軸上有\(n\)個點,從\(1\)到\(n\)編號。有\(m\)個操作,每次操作給出一個編號\(i \, 1 < i < n\),即把點\(i\)等概率移動到它關於點\(i-1\)的對稱點或關於點\(i+1\)的對稱點。記順序執行這\(m\)個操作為完成1次。問完成\(k\)次後,所有點的坐標的期望值是多少。
n, m \leq 10^5, , k \leq 10^{18}
首先,容易得到一個坐標為x的點,關於坐標為y的點對稱後,新點的坐標為2y - x。我們記點i的坐標為\(p_i\),那麽對它操作後得到的新點坐標的期望值就是\(\frac {2p_{i+1} + 2p_{i-1} -2p_i} {2} = p_{i+1} + p_{i-1} - p_i\)
因為期望有線性性,所以我們能確信,每一次操作就是把點\(i\)的坐標變為\(p_{i+1} + p_{i-1} - p_i\),最終答案就是每個點的坐標。
但我們還是難以解決這個問題。考慮這個性質:
\[
\begin{eqnarray*}
p_{i+1} - (p_{i+1} + p_{i-1} - p_i) &=& p_i - p_{i-1}\(p_{i+1} + p_{i-1} - p_i) - p_{i-1} &=& p_{i+1} - p_i
\end{eqnarray*}
\]
我們定義\(p'_i = p_i - p_{i-1}\),那麽,我們發現一次操作就是交換了\(p'_i\)
時間復雜度\(O(n)\)。
#include <bits/stdc++.h> using namespace std; const int N = 100010; typedef long long ll; int n,m,p[N],per[N],vis[N],ans[N],lop[N],cnt; ll k,val[N],res[N]; int main() { scanf("%d",&n); for (int i = 1 ; i <= n ; ++ i) scanf("%lld",&val[i]); scanf("%d%lld",&m,&k); for (int i = 1 ; i <= m ; ++ i) scanf("%d",&p[i]); for (int i = n ; i >= 1 ; -- i) val[i] = val[i] - val[i-1]; for (int i = 1 ; i <= n ; ++ i) per[i] = i; for (int i = 1 ; i <= m ; ++ i) swap(per[p[i]],per[p[i]+1]); for (int i = 1 ; i <= n ; ++ i) { if (vis[i]) continue; cnt = 0; lop[++cnt] = i; int pos = per[i]; while (pos != i) { vis[pos] = 1; lop[++cnt] = pos; pos = per[pos]; } for (int j = 1 ; j <= cnt ; ++ j) ans[lop[j]] = lop[(j + k - 1) % cnt + 1]; } for (int i = 1 ; i <= n ; ++ i) res[i] = val[ans[i]]; for (int i = 1 ; i <= n ; ++ i) res[i] += res[i-1]; for (int i = 1 ; i <= n ; ++ i) printf("%lld.0\n",res[i]); return 0; }
小結:這個特殊性質還是挺難找的。只能說找規律時,考慮差分、前綴和的變化是有用的。
【做題】agc006C - Rabbit Exercise——模型轉換