zoukankan      html  css  js  c++  java
  • CF1375F Integer Game 题解

    Codeforces
    Luogu

    Description.

    给你 \(a,b,c\),先手选择一个 \(x\in[1,10^12]\),后手选择 \(a,b,c\) 中一个数。
    然后在后手选择的数上加 \(k\),你需要吊打 spj。

    Solution.

    差一步啊啊啊啊啊啊啊啊啊啊,就真差一步就想打了啊啊啊啊啊。

    点击查看我差一步的所有笔记
    首先有 abc 每次 +=k  
    什么样的情况下先手会赢  
    后手不能连续对同一堆石子进行操作  
    那先手首先随便钦定一个,然后 +=k  
    后手选一个  
    先手选剩下两个的差  
    后手加到剩下两个偏大的里面去  
    所以相当于先手胜利的条件是局面构成等差数列且上一轮对最大的进行操作  
    但是后手肯定不会让这种局面出现,所以一个局面是先手必胜的当且仅当
    那也就相当于 max > mid*2 - min  
    否则我们需要证明后手必胜  
    
    首先,手模样例发现,如果 2*mid > min + max,此时先手必胜  
    同时有 2*c-a-b 加上后肯定可以变成上面的式子  
    他选择 2*mid - min - max 然后后手只能加中间然后继续选择 2*mid' - min - max 后手就 lose 了  
    如果 2*mid <= min + max 那后手先加到 max 上,所以先手先出 1
    相当于现在有 a b c 且满足 b-a < c-b
    划分成四个区间,[0,b-a]、[b-a,c-b]、[c-b,c-a]、[c-a,+inf]
    先手尝试让 min' + max' - 2*(sum'-min'-max') 尽可能小
    min' + max' - 2*(sum + x - min' - max')
    3*min' + 3*max' -2*sum - 2*x 小
    后手会尝试让他变大,所以会加到 max 上去
    如果不能加 max 那他会加到 min 上去
    3*min(mid,min+x)+3*max'-2*sum-2*x
    如果 x 很大,足以改变 max,显然不优
    如果 x 很小,肯定递增
    如果 x 中等,答案不变
    所以 x=mid-min,式子是 3*mid+3*max-2*sum-2*x
    所以先手给的肯定是 mid - min,后手肯定会把它加到最小值上去
    

    已经胡出了 \(2\times \text{mid} > \min + \max\),然后 \(2\times \max -\min -\text{mid}\) 这一步没想到,看了题解知道后最后一步也是自己想出来的。

    Coding.

    点击查看代码
    //是啊,你就是那只鬼了,所以被你碰到以后,就轮到我变成鬼了{{{
    #include<bits/stdc++.h>
    using namespace std;typedef long long ll;
    template<typename T>inline void read(T &x)
    {
    	x=0;char c=getchar(),f=0;
    	for(;c<48||c>57;c=getchar()) if(!(c^45)) f=1;
    	for(;c>=48&&c<=57;c=getchar()) x=(x<<1)+(x<<3)+(c^48);
    	f?x=-x:x;
    }
    template<typename T,typename...L>inline void read(T &x,L&...l) {read(x),read(l...);}//}}}
    pair<ll,int>a[5];
    inline void out(ll v)
    {
    	printf("%lld\n",v),fflush(stdout);ll x;read(x);
    	for(int i=1;i<=3;i++) if(a[i].second==x) a[i].first+=v;
    	sort(a+1,a+4);if(x==0) exit(0);
    }
    int main()
    {
    	for(int i=1;i<=3;i++) read(a[i].first),a[i].second=i;
    	puts("First"),fflush(stdout);
    	out(1000000005);
    	out(a[3].first*2-a[2].first-a[1].first);
    	out(a[3].first-a[2].first);
    	return 0;
    }
    
  • 相关阅读:
    IEnumerable、ICollection、IList、List关系和区别
    在Winform界面中使用DevExpress的TreeList实现节点过滤查询的两种方式
    关键字Lock的简单小例子
    .NET Core DI简单介绍
    Linux服务器部署.Net Core笔记:六、安装MySQL
    表的透视变换
    ZedGraph怎样在生成曲线时随机生成不一样的颜色
    3、手写Unity容器--第N层依赖注入
    微信支付-小程序H5 公众号 Payment SDK
    WPF继续响应被标记为已处理事件的方法
  • 原文地址:https://www.cnblogs.com/pealfrog/p/15414133.html
Copyright © 2011-2022 走看看