Codeforces Round #730 (Div. 2) A~D题解

本场链接:Codeforces Round #730 (Div. 2)

A. Exciting Bets

由性质:\((a + x,b + x) = (a + x,b - a)\)故取到最大值应该是\(a+x \mod b - a == 0\)时,就有最大值\(b-a\),步数为\(x\)解出即可.

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define forn(i,x,n) for(int i = x;i <= n;++i)
#define forr(i,x,n) for(int i = n;i >= x;--i)
#define Angel_Dust ios::sync_with_stdio(0);cin.tie(0)


int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        ll a,b;scanf("%lld%lld",&a,&b);
        if(a > b)   swap(b,a);
        if(a == b)  puts("0 0");
        else
        {
            ll c = b - a,s = ((-a) % c + c) % c;
            printf("%lld %lld\n",b - a,min(s,c - s));
        }
    }
    return 0;
}

B. Customising the Track

不难想到平均分配整个数组,且次序无关.

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define forn(i,x,n) for(int i = x;i <= n;++i)
#define forr(i,x,n) for(int i = n;i >= x;--i)
#define Angel_Dust ios::sync_with_stdio(0);cin.tie(0)

const int N = 2e5+7;
ll a[N];

int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        int n;scanf("%d",&n);
        forn(i,1,n) scanf("%lld",&a[i]);
        ll sum = 0;forn(i,1,n)  sum += a[i];
        ll c = sum % n;
        printf("%lld\n",(n - c) * c);
    }
    return 0;
}

C. Need for Pink Slips

不难想到因为\(v \geq 0.1\)所以总共的操作步数不会太多,又由于求期望的过程与当前三个概率的具体形态关联性紧密,所以枚举所有状态是一个非常可行的方向,不难想到一种将每一步取到终止状态的概率求出再总体求期望,但是由于精度问题挂掉了(傻逼).另外一种操作小一些的办法是期望dp,把状态表示成当前状态走到\((0,0,1)\)的步数,就可以确定终态的期望和转移了.

另外由于读入的就是浮点数,需要对其整数化处理.

不知道为什么扩大1e6倍后本机数据正常交上去会挂,写4e4和四舍五入能过,我只能说浮点数题我这辈子都不会做:)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define forn(i,x,n) for(int i = x;i <= n;++i)
#define forr(i,x,n) for(int i = n;i >= x;--i)
#define Angel_Dust ios::sync_with_stdio(0);cin.tie(0)

const int N = 2e5+7,M = 4e4;
int maxd;
ll v;


double dfs(ll c,ll m,ll p)
{
    double res = 1;
    if(c > 0)
    {
        ll pro = min(c,v);
        if(m == 0)          res += c * 1.0 / M * dfs(c - pro,0,p + pro);
        else                res += c * 1.0 / M * dfs(c - pro,m + pro / 2,p + pro / 2);
    }

    if(m > 0)
    {
        ll pro = min(m,v);
        if(c == 0)          res += m * 1.0 / M * dfs(0,m - pro,p + pro);
        else                res += m * 1.0 / M * dfs(c + pro / 2,m - pro,p + pro / 2);
    }
    return res;
}

int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        double c,m,p,_v;scanf("%lf%lf%lf%lf",&c,&m,&p,&_v);
        v = _v * M + 0.5;

        printf("%.18lf\n",dfs(ll(c * M + 0.5),ll(m * M + 0.5),ll(p * M + 0.5)));
    }
    return 0;
}

D1. RPD and Rap Sheet (Easy Version)

D1的情形等价于二进制的异或,不难根据异或的性质想到在询问了一个值\(y\)后,原本的答案\(x\)会变成\(x \oplus y\).由于答案的取值\(\in[0,n-1]\),不妨根据值域进行枚举,如果答案为\(x-1\),那么在第\(x\)次交互时,询问的值\(q_x\)需要等于当前的答案值(加密后的).

不妨一个一个处理:若\(ans == 0\)\(q_1 == 0\)显然,若\(ans == 1\)则在第一次交互之后,\(ans == 1\)此时的\(q_2 = 1 ^0\).继续可以推出\(q_i = (i-2) \oplus (i - 1)\).直接询问即可.

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define forn(i,x,n) for(int i = x;i <= n;++i)
#define forr(i,x,n) for(int i = n;i >= x;--i)
#define Angel_Dust ios::sync_with_stdio(0);cin.tie(0)

int query(int x)
{
    cout << x << endl;
    int res;cin >> res;
    return res;
}

int main()
{
    Angel_Dust;
    int T;cin >> T;
    while(T--)
    {
        int n,k;cin >> n >> k;
        if(query(0) == 1)   continue;
        forn(i,1,n) if(query(i ^ (i - 1)) == 1) break;
    }
    return 0;
}

D2. RPD and Rap Sheet (Hard Version)

与D1相同,首先想办法求出操作的逆操作,记作\(\ominus\),由模的性质可以拿到:\(x \oplus z == y\)推出\(z = y \ominus x\).同D1推导即可.

注意是后者\(\ominus\)前者.

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define forn(i,x,n) for(int i = x;i <= n;++i)
#define forr(i,x,n) for(int i = n;i >= x;--i)
#define Angel_Dust ios::sync_with_stdio(0);cin.tie(0)

int n,k;

int query(int x,int y)
{
    int z=0;
    int p=1;
    while(x>0 || y>0)
    {
        int a=x%k;
        x=x/k;
        int b=y%k;
        y=y/k;
        int c=(a-b+k)%k;
        z=z+p*c;
        p=p*k;
    }
    cout << z << endl;
    int res;cin >> res;
    return res;
}

int main()
{
    Angel_Dust;
    int T;cin >> T;
    while(T--)
    {
        cin >> n >> k;
        cout << 0 << endl;
        int res;cin >> res;
        if(res == 1)    continue;
        forn(i,2,n) 
        {
            if(i % 2 == 0)  if(query(i - 2,i - 1) == 1) break;
            if(i % 2 == 1)  if(query(i - 1,i - 2) == 1) break;
        }
    }
    return 0;
}

posted @ 2021-07-08 20:42  随处可见的阿宅  阅读(81)  评论(0编辑  收藏  举报