Codeforces Round #763 (Div. 2) D(推式子+概率)
Posted 吃花椒的妙酱
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #763 (Div. 2) D(推式子+概率)相关的知识,希望对你有一定的参考价值。
题目大意: 给n*m的矩阵,给机器人起点和垃圾的终点,一开始向右下移动,撞到边界时会反方向移动,当机器人与垃圾同行或者同列时有p/100的概率清理垃圾,求机器人清理掉垃圾的步数期望
思路:
法一:推式子
显然,机器人的路线是有一个周期T的,其中
T
=
l
c
m
(
2
∗
(
n
−
1
)
,
2
(
m
−
1
)
)
=
2
(
n
−
1
)
(
m
−
1
)
g
c
d
(
n
−
1
,
m
−
2
)
T=lcm(2*(n-1),2(m-1)) = \\frac2(n-1)(m-1)gcd(n-1,m-2)
T=lcm(2∗(n−1),2(m−1))=gcd(n−1,m−2)2(n−1)(m−1)
行的周期是2m-2,列的周期是2n-2,lcm就是总的周期了。
设ai是走到第i步时候,i-1步内未清理垃圾,第i步还没确定
设bi是走到第i步,清理垃圾的概率
a
n
s
=
∑
t
=
0
+
O
O
(
a
T
)
t
∑
i
=
0
T
(
i
+
t
T
)
∗
b
i
ans = \\sum_t=0^+OO (a_T)^t \\sum_i=0^T (i+tT) * b_i
ans=∑t=0+OO(aT)t∑i=0T(i+tT)∗bi
=
(
∑
i
=
0
T
i
∗
b
i
)
∗
1
1
−
a
T
+
T
(
∑
i
=
0
T
b
i
)
∗
∑
t
=
0
+
O
O
t
a
t
=(\\sum_i=0^T i*bi) * \\frac11-a_T + T(\\sum_i=0^T bi)*\\sum_t=0^+OOta^t
=(∑i=0Ti∗bi)∗1−aT1+T(∑i=0Tbi)∗∑t=0+OOtat
其中
∑
t
a
t
=
∑
[
(
t
+
1
)
a
t
−
a
t
]
=
∑
(
a
t
+
1
)
′
−
∑
a
t
,
先
求
和
再
导
一
下
,
最
后
得
\\sum ta^t = \\sum[(t+1)a^t -a^t] = \\sum(a^t+1)' - \\suma^t,先求和再导一下,最后得
∑tat=∑[(t+1)at−at]=∑(at+1)′−∑at,先求和再导一下,最后得
=
(
∑
i
=
0
T
i
∗
b
i
)
∗
1
1
−
a
T
+
T
(
∑
i
=
0
T
b
i
)
∗
a
T
(
1
−
a
T
)
2
=(\\sum_i=0^T i*bi) * \\frac11-a_T + T(\\sum_i=0^T bi)* \\fraca_T(1-aT)^2
=(∑i=0Ti∗bi)∗1−aT1+T(∑i=0Tbi)∗(1−aT)2aT
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<cstring>
#include<string>
#include<algorithm>
#include<math.h>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<deque>
#include <time.h>
#include<unordered_map>
using namespace std;
typedef long long ll;
#define IOS ios::sync_with_stdio(false),cin.tie(0)
#define _for(i,a,b) for(int i=(a) ;i<=(b) ;i++)
#define _rep(i,a,b) for(int i=(a) ;i>=(b) ;i--)
#define mst(v,s) memset(v,s,sizeof(v))
#define all(v) v.begin(),v.end()
#define AC return 0
#define pb(v) push_back(v)
#define INF 0x7f7f7f7f7f7f7f7f
#define inf 0x3f3f3f3f
#define int long long
#define pii pair<int ,int >
#define fi first
#define se second
#define endl "\\n"
const int N=4e5+10;
const int mod=1e9+7;
int n,k,m;
int dx,dy,sx,sy,ex,ey,p;
int a[N],b[N];
ll qsm(int a, int b)
ll ans=1,temp=a;
while(b)
if( b&1 ) ans = (ans * temp )%mod;
temp = (temp * temp)%mod;
b>>=1;
return ans;
ll gcd(int a ,int b)
while( b )
int t = a;
a = b;
b = t%b;
return a;
int ni(int x)return qsm(x%mod,mod-2);;
signed main()
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif
// IOS;
int T;cin>>T;
while( T-- )
cin>>n>>m>>sx>>sy>>ex>>ey>>p;
dx = 1, dy = 1;
int C = 2*(n-1)*(m-1)/gcd((n-1),(m-1));
p = p * ni(100) %mod;//化为分数
int sum_b=0;
int sum_ib=0;
a[0]=1;
_for(i,1,C)
int flag = (sx == ex || sy == ey );//第i-1步的状态
a[i] = ( a[i-1] * (1-flag*p+mod)%mod )%mod;
//ai,表示走了i-1步还没扔掉垃圾的几率
if( sx + dx < 1 || sx + dx > n ) dx *=-1;
if( sy + dy < 1 || sy + dy > m ) dy *=-1;
//第i步的状态
sx += dx;
sy += dy;
if(sx == ex || sy == ey ) b[i] = a[i] * p %mod;//bi, 第i步扔垃圾的概率
else b[i]=0;
sum_b = (sum_b + b[i])%mod;
sum_ib = (sum_ib + b[i]*i%mod)%mod;
int t = ni(1-a[C]+mod)%mod;
int ans1 = sum_ib * t %mod;
int ans2 = C * sum_b%mod * a[C]%mod * t %mod * t%mod;
cout<<(ans1 + ans2 )%mod<<endl;
AC;
法二:
设机器人一个周期的位置分别为1,2,3…k
设xi代表,机器人起点在第i个位置时,清理垃圾的期望步数
设ai代表,在第i个位置,作为起点时,清理垃圾的概率
则有
x1 = 0 + a1(1+x2)
x2 = 0 + a2(1+x3)
x3 = 0 + a3(1+x4)
…
xk = 0 + ak(1+x1)
联立得
x1 = a1(1+a2(1+a3(1+…+ak(1+x1))))
解方程即可
实属想不到QAQ,通过状态推方程
以上是关于Codeforces Round #763 (Div. 2) D(推式子+概率)的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces Round #763 (Div. 2) Editorial C 解题报告
Codeforces Round #763 (Div. 2) D(推式子+概率)
Codeforces Round #394 (Div. 2)