• Codeforces Round #763 (Div. 2)


    A

    直接 \(O(1)\) 用结论搞出来即可,但赛时发现范围很小就直接模拟了(注意到机器人在撞到上面和左面的墙并发生变速之前一定能够清除,只需要模拟撞下面、右面的墙)

    int main(){
    	int T; cin>>T;
    	while(T--){
    		int n, m, sx, sy, tx, ty;
    		cin>>n>>m>>sx>>sy>>tx>>ty;
    		
    		int dx=1, dy=1;
    		int res=0;
    		rep(i,1,420){
    			if(sx==tx || sy==ty) break;
    			if(sx==n) dx=-dx;
    			if(sy==m) dy=-dy;
    			sx+=dx, sy+=dy;
    			res++;
    		}
    		cout<<res<<endl;
    	}
    	return 0;
    }
    

    B

    对于每个区间,通过枚举断点,肯定能够找到对应的两个子区间(如果断点在端点那就是一个),模拟即可。

    const int N=1010;
     
    pii q[N];
     
    #define x first
    #define y second
     
    int main(){
    	int T; cin>>T;
    	while(T--){
    		int n; cin>>n;
    		set<pii> st;
    		
    		rep(i,1,n){
    			int x, y; read(x), read(y);
    			q[i]={x, y};
    			st.insert(q[i]);
    		}
    		
    		rep(i,1,n){
    			auto [x, y]=q[i];
    			if(x==y){
    				cout<<x<<' '<<x<<' '<<x<<endl;
    				continue;
    			}
    			rep(j,x,y){
    				if(j==x){
    					if(st.count({x+1, y})){
    						cout<<x<<' '<<y<<' '<<x<<endl;
    						break;
    					}
    				}
    				if(j==y){
    					if(st.count({x, y-1})){
    						cout<<x<<' '<<y<<' '<<y<<endl;
    						break;
    					}
    				}
    				if(st.count({x, j-1}) && st.count({j+1, y})){
    					cout<<x<<' '<<y<<' '<<j<<endl;
    					break;
    				}
    			}
    		}
    		// puts("");
    	}
    	return 0;
    }
    

    C

    对于这种最大化最小值的问题自然是二分

    设现在二分出一个 \(k\),也就是操作后元素都要不小于 \(k\),现在检测其可行性

    考虑贪心,为了防止前面的决策影响后面,我们从后面开始决策:我们自然是想要在保证后面大于 \(k\) 的前提下尽可能将物品分给前面的,最后我们检查一下决策后是否保证所有元素个数大于等于 \(k\) 即可。

    const int N=2e5+5;
     
    int a[N], b[N];
    int n;
     
    bool ok(int k){
    	rep(i,1,n) b[i]=a[i];
    	dwn(i,n,3){
    		int h=min(a[i]/3, (b[i]-k)/3);
    		b[i-1]+=h, b[i-2]+=2*h;
    	}
    	rep(i,1,n) if(b[i]<k) return false;
    	return true;
    }
     
    signed main(){
    	int T; cin>>T;
    	while(T--){
    		cin>>n;
    		rep(i,1,n) read(a[i]);
    		
    		int l=1, r=1e10;
    		while(l<r){
    			int mid=l+r+1>>1;
    			if(ok(mid)) l=mid;
    			else r=mid-1;
    		}		
    		cout<<l<<endl;
    	}
    	return 0;
    }
    

    D

    赛时我考虑将机器人可以清扫到污渍的点记为关键点,然后将关键点看成图论中的,边权是关键点之间的距离,然后得到一个环,但是写挂了呜呜。

    后来看了题解才发现可以写得很简单。

    记机器人执行清扫的概率为 \(\overline{p}\)

    我们设从出发点出发,期望清扫到污渍的步数为 \(x\),记机器人返回出发点且和最初出发时的朝向的步数为 \(k\)

    设出发点的后继期望清扫到污渍的步数为 \(y\),那么 \(x\)\(y\) 的关系为:\(x=w(1+y)\)

    其中,如果出发点为关键点,那么 \(w=\overline{p}\),否则为 \(1\)

    那么我们有 \(x = w_1(1 + w_2(1 + \dots w_k(1 + x)\dots))\)

    发现这其实是一个线性方程,可以化成 \(x=ux+v\) 的形式,因此可以逆向考虑(考虑得到右式),将 \(u,v\) 统计出来,细节见代码。

    const int N=1e5+5, mod=1e9+7;
    
    ll fpow(ll x, ll p){
        ll res=1;
        for(; p; p>>=1, x=x*x%mod)
            if(p&1) res=res*x%mod;
        return res%mod;
    }
    
    ll inv(ll x){
    	return fpow(x, mod-2)%mod;
    }
    
    int add(int a, int b){
    	return ((a+b)%mod+mod)%mod;
    }
    
    int mul(int a, int b){
    	return a*b%mod;
    }
    
    signed main(){
    	int T; cin>>T;
    	while(T--){
    		int n, m, sx, sy, tx, ty, p;
    		cin>>n>>m>>sx>>sy>>tx>>ty>>p;
    		p=mul(add(100, -p), inv(100));
    		
    		int ux=sx, uy=sy;
    		int u=1, v=0;
    		int dx=-1, dy=-1;
    		rep(i,1,4*(n-1)*(m-1)){
    			if(ux+dx<1 || ux+dx>n) dx=-dx;
    			if(uy+dy<1 || uy+dy>m) dy=-dy;
    			
    			ux+=dx, uy+=dy;
    			v=add(v, 1);
    			int w;
    			if(ux==tx || uy==ty) w=p;
    			else w=1;
    			u=mul(u, w), v=mul(v, w);
    		}
    		
    		cout<<(mul(v, inv(add(1, -u))))<<endl;
    	}
    	return 0;
    }
    
  • 相关阅读:
    java之获取变量的类型
    java中的++和--
    java(三)基础类型之间的转换
    golang数据结构之总结
    golang数据结构之树的三种遍历方式
    golang数据结构之散哈希表(Hash)
    golang数据结构之递归解决迷宫问题
    golang数据结构之利用栈求计算表达式(加减乘除)
    golang数据结构之栈
    golang数据结构之快速排序
  • 原文地址:https://www.cnblogs.com/Tenshi/p/15747253.html
Copyright © 2020-2023  润新知