「EZEC-6」跳一跳
Description
跳一跳规则如下:
- 设定一个计数器
\text{cnt} ,将其初始值设置为2 。 - 若跳上下一个格子但没跳到其中心,加
1 分,将\text{cnt} 重置为2 。 - 若跳上下一个格子且跳到了其中心,加
\text{cnt} 分,将\text{cnt} 翻倍。 - 若下一个格子为特殊格
x_i 且跳到了其中心,额外加y_i 分。 - 终止条件为没跳上下一个格子或者跳完了所有格子。
已知共有
小 A 跳上下一个格子但没跳到其中心的概率为
求他的期望得分,并对
Solution
转移矩阵好像还有好多种,那我就再来一种。
首先加分大致有两种:
- 跳到某个格子,根据
2,3 规则加分; - 跳到指定格子的中心,获得指定加分。
两者之间没有太大关系,可以分开考虑。
对于第二种,只要求出跳到
对于第一种,看看能不能找规律,设
密密麻麻的,放在一起看:
那递推式不就是:
然后再求一个前缀和。但是还不够:
根据上述两个式子,先构造出一个矩阵(把式子里有用的都加进去):
然后尝试构造出转移矩阵:
那么:
看到这么多
最后回过头来再看我们的这个式子:
考虑正向推导一下:
- 跳到第
n 格的中心。事实上如果把规则2 的“加1 分”理解为“将\text{cnt} 重置为1 ,然后进入规则3 ”,那么我跳到n 的中心后,就是把跳到n-1 格的所有贡献都乘上2 ,即“\text{cnt} 翻倍”了,然后再乘上概率b\% 。贡献是f_{n-1}\times2b\% 。 - 跳到第
n 格但没跳到中心。基本与跳特殊格类似,首先算出跳到n-1 格的概率,只不过最后乘上的是a\% 。贡献是(a\%+b\%)^{n-1}a\% 。
剩下的套个模板就行。时间复杂度
不开 long long 见祖宗!!WA 了两发,先是 n 没开,又是 x 没开。
Code
#include <iostream>
#define ll long long
using namespace std;
const int mod = 1000000007;
ll n;
int a, b, m;
ll read(){
ll x = 0;
bool tf = 0;
char a = getchar();
while(a < '0' || '9' < a) a == '-'? tf = 1: -1 ,a = getchar();
while('0' <= a && a <= '9') x = (x << 1) + (x << 3) + (a ^ 48), a = getchar();
return tf? -x: x;
}
void write(int x){
if(x > 9) write(x / 10);
putchar(x % 10 | 48);
}
struct mat{
int a[3][3];
mat operator *(const mat &nex){
mat ans;
for(int i = 0; i < 3; ++ i)
for(int j = 0; j < 3; ++ j){
ans.a[i][j] = 0;
for(int k = 0; k < 3; ++ k)
ans.a[i][j] = (ans.a[i][j] + (ll)a[i][k] * nex.a[k][j]) % mod;
}
return ans;
}
} ans, base;
void inv(int &a){
int p = mod - 2, base = 100;
while(p > 0){
if(p & 1) a = (ll)a * base % mod;
base = (ll)base * base % mod;
p >>= 1;
}
}
int main(){
n = read(), a = read(), b = read();
inv(a), inv(b);
ans.a[0][1] = (a + (b << 1) % mod) % mod, ans.a[0][2] = (a + b) % mod;
base.a[0][0] = 1, base.a[1][0] = 1;
base.a[1][1] = (b << 1) % mod, base.a[2][1] = a;
base.a[2][2] = (a + b) % mod;
while(n > 0){
if(n & 1) ans = ans * base;
base = base * base;
n >>= 1;
}
m = read();
for(int i = 1; i <= m; ++ i){
ll x = read() - 1;
int y = read(), v = b, t = a + b;
while(x > 0){
if(x & 1) v = (ll)v * t % mod;
t = (ll)t * t % mod;
x >>= 1;
}
ans.a[0][0] = (ans.a[0][0] + (ll)y * v) % mod;
}
write(ans.a[0][0]);
return 0;
}