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(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) * \\frac11-a_T + T(\\sum_i=0^T bi)*\\sum_t=0^+OOta^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)' - \\suma^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) * \\frac11-a_T + T(\\sum_i=0^T bi)* \\fraca_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,通过状态推方程

以上是关于Codeforces Round #763 (Div. 2) D(推式子+概率)的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces Round #763 (Div. 2) Editorial C 解题报告

Codeforces Round #763 (Div. 2) D(推式子+概率)

Codeforces Round #394 (Div. 2)

Codeforces Round #436 E. Fire(背包dp+输出路径)

codeforces763B

[ACM]Codeforces Round #534 (Div. 2)