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)) = \frac{2(n-1)(m-1)}{gcd(n-1,m-2)} T=lcm(2(n1),2(m1))=gcd(n1,m2)2(n1)(m1)

行的周期是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)ti=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) * \frac{1}{1-a_T} + T(\sum_{i=0}^T bi)*\sum_{t=0}^{+OO}ta^t =(i=0Tibi)1aT1+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})}' - \sum{a^t},先求和再导一下,最后得 tat=[(t+1)atat]=(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) * \frac{1}{1-a_T} + T(\sum_{i=0}^T bi)* \frac{a_T}{(1-aT)^2} =(i=0Tibi)1aT1+T(i=0Tbi)(1aT)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,通过状态推方程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值