[洛谷] AT2164 [AGC006C] Rabbit Exercise
Description
Solution
一道好题,涉及到差分化简以及倍增求置换。
注意到一次操作后,\(a[i]\)的位置期望为\(E(a[i])=\frac{1}{2}(E(2a[i+1]-a[i])+E(2a[i-1]-a[i]))=E(a[i+1]+a[i-1]-a[i])\)
这么看不太好求。但对\(a\)差分后,发现一次这样的操作就是对差分数组\(d\)进行\(swap(d[i],d[i+1])\)。
那么就是对\(d\)进行\(k\)轮置换。注意到\(k\)很大,可以通过倍增优化,和快速幂类似。
即我们记录两个数组\(p\)和\(q\),\(p\)保存置换一轮后的结果,相当于快速幂的\(base\)。而\(q\)保存答案即可。
Code
#include <bits/stdc++.h>
using namespace std;
#define ll long long
int n, m, x[100005], p[100005], q[100005], a[100005], cnt[100005];
ll sum, k;
int read()
{
int x = 0, fl = 1; char ch = getchar();
while (ch < '0' || ch > '9') { if (ch == '-') fl = -1; ch = getchar();}
while (ch >= '0' && ch <= '9') {x = (x << 1) + (x << 3) + ch - '0'; ch = getchar();}
return x * fl;
}
int main()
{
n = read();
for (int i = 1; i <= n; i ++ )
{
x[i] = read();
p[i] = q[i] = i;
}
m = read(); scanf("%lld", &k);
for (int i = 1; i <= m; i ++ )
{
a[i] = read();
swap(p[a[i]], p[a[i] + 1]);
}
while (k)
{
// printf("%lld\n", k);
if (k & 1ll)
{
for (int i = 1; i <= n; i ++ )
cnt[i] = q[p[i]];
for (int i = 1; i <= n; i ++ )
q[i] = cnt[i];
}
for (int i = 1; i <= n; i ++ )
cnt[i] = p[p[i]];
for (int i = 1; i <= n; i ++ )
p[i] = cnt[i];
k >>= 1ll;
}
for (int i = 1; i <= n; i ++ )
{
sum += (ll)(x[q[i]] - x[q[i] - 1]);
printf("%.1lf\n", (double)(sum));
}
return 0;
}