Robot Cleaner Revisit(CF)

Codeforces Round #763 (Div. 2)

D. Robot Cleaner Revisit

题目链接:https://codeforces.com/contest/1623/problem/D
解题代码来自于cf某大佬 :By AlanSkarica;

思路:

由于最多只有n ∗ * ∗m个点,所以循环的点最多n ∗ * ∗m个,又因为边缘只有两种状态,顶点只有一种状态,故共有4(m-1)(n-1)种状态点,且4(m-1)(n-1)一定是环的边长的整数倍,对于每k种状态x1,x2…xk,每个状态可能的情况都是 p / 100 p/100 p/100,对于x1,若在x1点清扫 则需0s,若不在则需 x x x2 + 1 + 1 +1 s,以此类推若此点可清楚xk = (1-p/100)(1 + x1),不能清楚则xk = (1 + x1);
最终便可得到方程:
x=a1(1+a2(1+a3(1+…ak(1+x)…)))
ai表示第i个点可以消除。
同时该式可改写成 x = u + vx 的形式,最后所求 x = u/(1-v);

这里由于mod为质数,故可用费马小定理来求解 x⋅(1-v)≡u,最终 x = u*(1-v)^{mod - 2}^

代码:

#include<iostream>

using namespace std;
const int mod = 1e9 + 7;
typedef long long ll;

int add(int x,int y){
	x += y;
	while(x >= mod) x -= mod;
	while(x < 0) x += mod;
	return x;
}

int mul(int x,int y){
	return ( x * 1ll* y) % mod;
}

int binpow(int x,int y){
	int c = 1;
	while(y){
		if(y % 2 == 1) c = mul(c,x);
		x = mul(x,x);
		y /= 2;
	}
	return c;
}

int inv(int x){
	return binpow(x,mod - 2);
}

int divide(int x,int y){
	return mul(x,inv(y));
}

void solve()
{
	int n,m,rb,cb,rd,cd,p;
	scanf("%d%d%d%d%d%d%d",&n,&m,&rb,&cb,&rd,&cd,&p);
	p = add(1,-divide(p,100));
	
	int u = 0 , v = 1 , dr = -1 , dc = -1;
	
	for(int i = 0 ; i < 4 * ( m - 1) * (n - 1) ; i++){
		if(rb + dr < 1 || rb + dr > n) dr *= -1;
		if(cb + dc < 1 || cb + dc > m) dc *= -1;
		rb += dr;
		cb += dc;
		
		u = add(u,1);
		if(rb == rd || cb == cd){
			u = mul(u,p);
			v = mul(v,p);
		} 
	}
	cout<<divide(u,add(1,-v))<<"\n";
}
int main()
{
	
	int tt;
	scanf("%d",&tt);
	while(tt--){
		solve();
	}
	return 0;
 } 
上一篇:gitlab集成CICD


下一篇:ShareSDK自定义UI的方法