题目:https://www.nowcoder.com/acm/contest/147/E
Niuniu likes to play OSU!
We simplify the game OSU to the following problem.
Given n and m, there are n clicks. Each click may success or fail.
For a continuous success sequence with length X, the player can score X^m.
The probability that the i-th click success is p[i]/100.
We want to know the expectation of score.
As the result might be very large (and not integral), you only need to output the result mod 1000000007.
输入描述:
The first line contains two integers, which are n and m.
The second line contains n integers. The i-th integer is p[i].
1 <= n <= 1000
1 <= m <= 1000
0 <= p[i] <= 100
输出描述:
You should output an integer, which is the answer.
这个题有 O(n2) O ( n 2 ) 的做法,这里不多加讨论。说下从bls学到的用第二类 Stirling S t i r l i n g 数优化计算 xm x m 的方法。
设 x x 为最长连续成功后缀的长度。设 a[i][j] a [ i ] [ j ] 为考虑前i次点击, xj x j 的期望。
由二项式定理可知
合并起来就是
这样做的复杂度是 O(nm2) O ( n m 2 )
先放一个结论
这个可以在组合数学的教材里找到。
[n]k [ n ] k 表示n的下阶乘,等价于 A(n,k) A ( n , k ) 。 S(p,k) S ( p , k ) 表示第二类 stirling s t i r l i n g 数
那么我们可以将维护 np n p 的期望 转换到维护 (nk) ( n k ) 的期望上去。
同样的,我们设最长成功后缀的长度为 x x ,设 a[i][j] a [ i ] [ j ] 为 考虑到第i 位后 (xj) ( x j ) 的期望,设 b[i][j] b [ i ] [ j ] 为所有 (xj) ( x j ) 的期望。
由杨辉三角:
至此,这道题就可以能够在 O(nm) O ( n m ) 的时间内完成.
#include
using namespace std;
int n, m, mod = 1000000007;
long long p[1020];
long long a[1020][1020];
long long b[1020][1020];
long long s[1020][1020];
long long f[1020];
typedef long long ll;
int main() {
scanf("%d%d", &n, &m);
s[0][0] = 1;
for (int i = 0; i <= m; i++) {
for (int j = 1; j <= i; j++) {
s[i][j] = (s[i - 1][j - 1] + j * s[i - 1][j]) % mod;
}
}
for (int i = f[0] = 1; i <= m; i++) {
f[i] = f[i - 1] * i % mod;
}
a[0][0] = 1;
for (int i = 1; i <= n; i++) {
scanf("%lld", &p[i]);
p[i] = p[i] * 570000004 % mod;
a[i][0] = 1;
for (int j = 1; j <= m; j++) {
a[i][j] = a[i-1][j] + a[i-1][j - 1];
a[i][j] *= p[i];
a[i][j] %= mod;
b[i][j] = p[i] * a[i-1][j-1];
b[i][j] %= mod;
b[i][j] += b[i-1][j];
b[i][j] %= mod;
}
}
long long z = 0;
for (int i = 1; i <= m; i++) {
z = (z + b[n][i] * f[i] % mod * s[m][i]) % mod;
}
printf("%lld\n", z);
return 0;
}