链接:https://www.nowcoder.com/acm/contest/147/E
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
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.
示例1
复制
3 4
50 50 50
复制
750000020
000 0
001 1
010 1
011 16
100 1
101 2
110 16
111 81
The exact answer is (0 + 1 + 1 + 16 + 1 + 2 + 16 + 81) / 8 = 59/4.
As 750000020 * 4 mod 1000000007 = 59
You should output 750000020.
If you don't know how to output a fraction mod 1000000007,
You may have a look at https://en.wikipedia.org/wiki/Modular_multiplicative_inverse
感觉最近需要好好补一下数学方面的题目包括概率期望什么的 平时接触的太少了
看题解说要用什么第二类斯特林数 什么玩意啊 根本没听过 多校赛到处都是别人很熟的而我们听都没听过的东西
但是看了一下别的题解其实也没有那么难吧
顺便学习了一下分数取模的方法
一个数a乘一个数b对p取模 和a乘b的逆元对p取模结果是一样的
求逆元最方便的方法是用扩展欧几里得
https://blog.csdn.net/stray_lambs/article/details/52133141这篇博客讲欧几里得讲的还是蛮细的
但是我还是没有很明白题解里求的inv 是什么道理
下面说说题目的主体思路
首先用快速幂预处理得分
用pos[i][j]表示从 i 到 j 这段区间全部是获胜的概率
pos[i][j]肯定是可以有pos[i][j - 1]推出来的
枚举i , j 表示从i + 1 到 j - 1都连续胜利利用期望的可加性E(X+Y)=E(X)+E(Y);
这段的期望就是(i失败的概率)*(j失败的概率)*(i-j连续获胜的概率)*(分数)
#include
#include
#include
#include
#include
#define inf 1e18
using namespace std;
const long long mod = 1e9 + 7;
const int maxn = 1005;
long long m, n, p[maxn];
long long ipowm[maxn], pos[maxn][maxn];
long long qpow(long long x, long long m)
{
long long ans = 1;
while(m){
if(m & 1){
ans = ans * x % mod;
}
x = x * x % mod;
m = m >> 1;
}
return ans;
}
long long exgcd(long long a, long long b, long long &x, long long &y)
{
if(a == 0 && b == 0)
return -1;
if(b == 0){
x = 1;
y = 0;
return a;
}
long long d = exgcd(b, a % b, y, x);
y -= a / b * x;
return d;
}
//扩展欧几里得求逆元 用于分数取模
long long mod_rev(long long a, long long n)
{
long long x, y;
long long d = exgcd(a, n, x, y);
if(d == 1)
return (x % n + n) % n;
else return -1;
}
int main()
{
long long inv = mod_rev(100ll, mod);//因为这里概率还要除以100,所以第一个参数写100, 第二个参数就是模
//cout<