原题传送门
题面易懂
首先,感到无从下手,只会20%的
O
(
k
n
)
O(k^n)
O(kn)暴力
然后苦(kan)思(kan)冥(ti)想(jie)发现可以直接推公式
分成两种情况讨论
- 对于每个位置,可以做 k k k种动作,所以概率为 1 k \frac{1}{k} k1,获得的威力收益是 v a l [ i ] val[i] val[i],所以期望是 ∑ i = 1 k v a l [ i ] k = ∑ i = 1 k v a l [ i ] k \sum_{i=1}^{k}\frac{val[i]}{k}=\frac{\sum_{i=1}^{k}val[i]}{k} ∑i=1kkval[i]=k∑i=1kval[i],那么总共有n个位置,总的期望是 n ∗ ∑ i = 1 k v a l [ i ] k \frac{n*\sum_{i=1}^{k}val[i]}{k} kn∗∑i=1kval[i]
- 对于每两个相邻位置,额外可能会有连招的情况出现,出现的概率为 1 k 2 \frac{1}{k^2} k21,获得威力 v a l [ i ] + v a l [ i + 1 ] val[i]+val[i+1] val[i]+val[i+1],当然 v a l [ k ] 与 v a l [ 1 ] 也 是 可 以 的 val[k]与val[1]也是可以的 val[k]与val[1]也是可以的,那么期望是 ∑ i = 1 k v a l [ i ] + v a l [ n e x t ( i ) ] k 2 = ∑ i = 1 k v a l [ i ] + v a l [ n x t ( i ) ] k 2 \sum_{i=1}^{k}\frac{val[i]+val[next(i)]}{k^2}=\frac{\sum_{i=1}^{k}val[i]+val[nxt(i)]}{k^2} ∑i=1kk2val[i]+val[next(i)]=k2∑i=1kval[i]+val[nxt(i)],总共有 ( n − 1 ) (n-1) (n−1)组相邻位置,总的期望是 ( n − 1 ) ∗ ∑ i = 1 k v a l [ i ] + v a l [ n x t ( i ) ] k 2 \frac{(n-1)*\sum_{i=1}^{k}val[i]+val[nxt(i)]}{k^2} k2(n−1)∗∑i=1kval[i]+val[nxt(i)]
两个式子加起来就是答案~~
化简一下
记
s
u
m
=
∑
i
=
1
k
v
a
l
[
i
]
sum=\sum_{i=1}^{k}val[i]
sum=∑i=1kval[i]
那么
n
∗
∑
i
=
1
k
v
a
l
[
i
]
k
=
n
∗
s
u
m
k
\frac{n*\sum_{i=1}^{k}val[i]}{k}=\frac{n*sum}{k}
kn∗∑i=1kval[i]=kn∗sum
(
n
−
1
)
∗
∑
i
=
1
k
v
a
l
[
i
]
+
v
a
l
[
n
x
t
(
i
)
]
k
2
=
2
s
u
m
∗
(
n
−
1
)
k
2
\frac{(n-1)*\sum_{i=1}^{k}val[i]+val[nxt(i)]}{k^2}=\frac{2sum*(n-1)}{k^2}
k2(n−1)∗∑i=1kval[i]+val[nxt(i)]=k22sum∗(n−1)
加起来:
n
∗
s
u
m
k
+
2
s
u
m
∗
(
n
−
1
)
k
2
=
s
u
m
∗
n
∗
k
+
2
s
u
m
∗
(
n
−
1
)
k
2
=
s
u
m
(
n
k
+
2
n
−
2
)
k
2
\frac{n*sum}{k}+\frac{2sum*(n-1)}{k^2}=\frac{sum*n*k+2sum*(n-1)}{k^2}=\frac{sum(nk+2n-2)}{k^2}
kn∗sum+k22sum∗(n−1)=k2sum∗n∗k+2sum∗(n−1)=k2sum(nk+2n−2)
直接一开始把sum求出来,n再大也没关系,一边读入一边取模即可
变成一道结论题,开心
Code:
#include <bits/stdc++.h>
#define maxn 1000010
#define qy 19491001
#define LL long long
using namespace std;
inline int read(){
int s = 0, w = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
return s * w;
}
LL ksm(LL n, int k){
if (!k) return 1;
LL sum = ksm(n, k >> 1);
sum = sum * sum % qy;
if (k & 1) sum = sum * n % qy;
return sum;
}
int main(){
LL n = 0;
char c = getchar();
for (; !isdigit(c); c = getchar());
for (; isdigit(c); c = getchar()) n = ((n << 1) + (n << 3) + (c ^ 48)) % qy;
LL k = read(), sum = 0;
for (int i = 1; i <= k; ++i){
int x = read();
(sum += x) %= qy;
}
LL nk = n * k % qy;
printf("%lld\n", sum * ((nk + 2 * n - 2) % qy + qy) % qy * ksm(k * k % qy, qy - 2) % qy);
return 0;
}

博客围绕LuoGu上的题目展开题解。起初只能用20%的O(kn)暴力法,后经思考推导出公式。分每个位置和每两个相邻位置两种情况讨论期望,得出两个式子,化简后得到最终答案,还提到可边读入边取模,将其变为结论题。
1070

被折叠的 条评论
为什么被折叠?



