牛客寒假算法基础集训营6 - F 石头剪刀布 构造

题目链接

题意:一共三种人,喜欢石头、剪刀、布,设定为喜欢石头的和喜欢剪刀的玩,喜欢石头的赢,以此类推。设一共 2 n 2^n 2n 个人,编号为 1 1 1 2 2 2 3 3 3,…, 2 n 2^n 2n,其中第一轮 1 1 1 2 2 2 比,然后胜者与 3 3 3 4 4 4 的胜者比,一轮一轮下去直到只剩一个人,现在给定 2 n 2^n 2n 个人的喜好,问如何安排编号顺序,能保证比赛进行过程中不会出现喜好相同的人进行比赛。

思路:设某一轮可行解为 a a a 个石头, b b b 个剪刀, c c c 个布,可以退出上一轮可行解为 a + c a+c a+c 个石头, a + b a+b a+b 个剪刀, b + c b+c b+c个布,由此,枚举结果(只有三种结果),然后推到输入所给当前那轮,即可判断输入是否为可行解。若可行,对于一个正确解,同样可以用递推的方式,记 d p [ i ] : 0 dp[i]:0 dp[i]0 为结果为布的字典序最小的解, 1 1 1 为石头, 2 2 2 为剪刀,所以对于下一轮的 d p dp dp 数组,可以通过当前轮的解推出。

#include <cstdio>
#include <iostream>
using namespace std;
#define ffor(i,d,u) for(int i=(d);i<=(u);++i)
#define _ffor(i,u,d) for(int i=(u);i>=(d);--i)
int r, p, s;
int total;
string str[3], mstr[3];//0:值为P(布),1:值为R(石头),2:值为S(剪刀)
int in[3][2] = {{0, 1}, {1, 2}, {2, 0}};
bool check(const int &ar, const int &ap, const int &as)
{
    int mr, mp, ms;
    mr = ar + ap, mp = ap + as, ms = as + ar;
    if ((mr + mp + ms) == total)
        return (mr == r && mp == p && ms == s);
    return check(mr, mp, ms);
}
void print(int length)
{
    if (length == total)
        return;
    mstr[0] = str[0], mstr[1] = str[1], mstr[2] = str[2];
    ffor(i, 0, 2)
        if (mstr[in[i][0]] > mstr[in[i][1]])
            str[i] = mstr[in[i][1]] + mstr[in[i][0]];
        else
            str[i] = mstr[in[i][0]] + mstr[in[i][1]];
    print(length << 1);
}
inline void AC()
{
    cin >> r >> p >> s;
    total = r + p + s;
    str[0] = "PR", str[1] = "RS", str[2] = "PS";
    print(2);
    int ar, ap, as;
    ar = 1, ap = 0, as = 0;
    if (check(ar, ap, as))
    {
        cout << str[1];
        return;
    }
    else
    {
        ar = 0, ap = 1, as = 0;
        if (check(ar, ap, as))
        {
            cout << str[0];
            return;
        }
        else
        {
            ar = 0, ap = 0, as = 1;
            if (check(ar, ap, as))
            {
                cout << str[2];
                return;
            }
            else
                puts("IMPOSSIBLE");
        }
    }
}
int main()
{
    AC();
    return 0;
}
### 关于2020年牛客寒假算法基础集训营中的欧几里得算法 在2020年的牛客寒假算法基础集训营中,确实存在涉及欧几里得算法的相关题目。具体来说,在第四场竞赛的第一题即为“A. 欧几里得”,该题目的核心在于利用扩展欧几里得定理来解决问题[^5]。 #### 扩展欧几里得算法简介 扩展欧几里得算法主要用于求解形如 ax + by = gcd(a, b) 的线性不定方程的一组特解(x,y),其中gcd表示最大公约数。此方法不仅能够计算两个整数的最大公因数,还能找到满足上述条件的具体系数x和y。 对于给定的数据范围较小的情况可以直接通过递归来实现;而对于较大数据则需考虑效率优化问题。下面给出了一段基于C++语言编写的用于解决此类问题的模板代码: ```cpp #include<bits/stdc++.h> #define int long long using namespace std; // 定义全局变量存储结果 int x, y; void ex_gcd(int a, int b){ if(b == 0){ x = 1; y = 0; return ; } ex_gcd(b, a % b); int tmp = x; x = y; y = tmp - (a / b) * y; } ``` 这段程序实现了经典的扩展欧几里得算法逻辑,并且可以作为处理类似问题的基础工具函数调用。 #### 实际应用案例分析 回到原题本身,“A. 欧几里得”的解答思路就是先预处理斐波那契数列前若干项数值存入数组`a[]`内以便快速查询,之后针对每一次询问直接输出对应位置处两相邻元素之和即可得出最终答案。这实际上巧妙运用到了广为人知的裴蜀定理——任意一对互质正整数都可由它们自身的倍数组合而成,而这里正是借助了这一性质简化了解决方案的设计过程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值