EOJ Monthly 2018.1 - (A,B)

本文介绍了一种在石头剪刀布锦标赛中提高胜率的策略。通过分析对手的出拳频率并利用优先级概念,可以在100局比赛中制定有效的应对方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

EOJ Monthly 2018.1

A. 石头剪刀布的套路

Time limit per test: 1.0 seconds

Memory limit: 256 megabytes

现在有一种石头剪刀布锦标赛。采取 100 局胜负制。对战 100 局,扣掉平局,谁赢得多谁就取得最终的胜利。

zzz 同学天天玩石头剪刀布,从而总结出了一套提高石头剪刀布胜率的方法。这套方法重点在于利用人的心理。石头剪刀布这三者,你可能觉得你是随机选择的,但其实不然。你还是会产生一定的偏向性。在若干局游戏后,有的人出石头的频数会高,有的人出布的频数会高,还有的人出剪刀的频数会高。

这点差异其实微乎其微,但却能成为决定胜负的关键。zzz 同学也就是靠着这微乎其微的差异,拿到了石头剪刀布世界冠军,攀上人生巅峰。

作为 zzz 同学的室友,你对 zzz 同学出石头剪刀布的套路掌握得一清二楚。具体如下:

  • 他会根据对方之前已经出过的石头次数、剪刀次数、布次数,来决定最不利于对方的。比如对方剪刀最多,他一定会出石头;对方布最多,他一定会出剪刀;对方石头最多,他一定会出布。
  • 在比赛开始前,他会给石头剪刀布各分配一个优先级,分别为  p,q,r 。如果存在两个一样多,或三个一样多,或者一个都没出过(刚开局),那么他会优先选择优先级高的。比如说对方出过的剪刀和布一样多,石头就比较少,那么他接下来的选择一定在石头和剪刀之间。如果石头的优先级为  3 ,剪刀的优先级为  2 ,那么他就会优先选择石头。

zzz 同学是很死板的,他肯定不会违背这套策略。也就是说,一旦你搞到了他即将参加的比赛的优先级  p,q,r ,你基本已经赢了,甚至连这 100 局每局是输是赢都想好了。

于是你膨胀了。你要去挑战世界冠军 zzz。

Input

有且仅有一行,三个整数  p,q,r  ( {p,q,r}={1,2,3} ),用空格隔开。

不会有两个相同的测试点。

Output

输出  100  行,每行一个整数,依次为这 100 局你的选择。

石头输出  1 ,剪刀输出  2 ,布输出  3

Note

此题无样例。


分析:  其实我们在比赛中要赢zzz,而且注意题目其实是100局中每一局都是可控的。注意:"他会根据对方之前已经出过的石头次数、剪刀次数、布次数,来决定最不利于对方的“,这里的利用是实时的,即随着100局的推进而判断。而且对于优先级,那么我们很容易想到通过我们的选择利用优先级,而且我们一定是均匀选择石头剪刀布而不给对方机会的。

   第一步:在知道对方优先级的情况下,由于一开局没有我方的选择记录,所以zzz只能选择优先级最高的一个,我们就选择可以克制它的,这是我们利用的第一步,第二步,由于我方已经选择了一次,无论选了什么此时它都是我方选的最多的,那么根据规则zzz一定选择可以克制我方选的最多的这张牌,于是我们又知道了zzz第二步选哪张,我再选择克制zzz的就行,对于第三步,我们只要选择前两局我方未选择过的,用来平均之前的选择记录就好,这样至少保证3局赢2局。

代码:

#include<iostream>
#include<string>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<math.h>
#include<iomanip>
#include<queue>
#include<cstring>
#include<map>
using namespace std;
typedef long long ll;
#define M 10

int main()
{
    int p,q,r,i;
    int a[4];

    while(scanf("%d%d%d",&p,&q,&r)!=EOF)
    {
        int maxv=max(p,max(q,r));
        //int minv=min(p,min(q,r));
        if(p==maxv)
        {
            a[1]=3;
            a[2]=1;
            a[3]=2;
        }else if(q==maxv)
        {
            a[1]=1;
            a[2]=2;
            a[3]=3;
        }else {
            a[1]=2;
            a[2]=3;
            a[3]=1;
        }
        for(i=1;i<=33;i++)
        {
            cout<<a[1]<<endl;
            cout<<a[2]<<endl;
            cout<<a[3]<<endl;
        }
        cout<<a[1]<<endl;
    }
    return 0;
}

B. 最大的子串

Time limit per test: 1.0 seconds

Memory limit: 256 megabytes

字符串的大,不在于长,而在于

现在给出由数字组成的字符串  s ,求出字符串的所有的非空连续子串中,最妙的那个子串。

一个字符串的妙是这样定义的:将这个子串所表示的整数(有可能带前导 0),除以  10L (其中  L  为字符串的长度)。比如说 123456789 的子串 456 的妙为  456103=0.456

Input

给出一行一个字符串  s  ( 1|s|20 000 )。

Output

输出最妙的那个子串。如果有多个,输出最短的那个。如果最短的最妙的子串也有多个,输出字典序最小的那个。

Examples

input
123456789
output
9
input
321
output
321

题目让输出妙值最大的子串,正确答案的首位一定是数字串中最大的一位数,末位直到字符串最后一个非0字符 (也就是对于正确答案结果尾部的0要都去掉),那么我们可以直接枚举每一个判断妙值就好,

其实也根本没有所谓的字典序最小,正确答案的字典序是唯一的,对于“输出最短的”也只是去掉尾部的0,因为如果对于每一位都非0的两个答案,而且他们的每一位对应相等,那么比较长的一个才是正确答案。


代码:

#include<iostream>
#include<string>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<math.h>
#include<iomanip>
#include<queue>
#include<cstring>
#include<map>
using namespace std;
typedef long long ll;
#define M 20005
char str[M];
int len;
bool ok[M];

void not_ok(int it) 
{
    memset(ok,false,sizeof(ok));
    int i;
    for(i=len-1;i>it;i--)
    {
        if(str[i]=='0')
        {
            ok[i]=true;
        }else{
            break;
        }
    }
}

int main()
{
    scanf("%s",str);
    int i,j;
    len=strlen(str);
    int ans=0,loc=0,maxv=0;
    for(i=0;i<len;i++)
    {
        int tmp=str[i]-'0';
        if(tmp>maxv)
        {
            maxv=tmp;
            ans=i;
        }else if(tmp==maxv)
        {
            loc=i;
            int L=len-loc;
            for(j=1;j<L;j++) //判断两个待选答案的每一位,
            {
                if(str[ans+j]>str[loc+j]) //ans对应的答案从某一位开始大于loc对应的答案,ans正确
                {
                    break;
                }else if(str[ans+j]<str[loc+j]) //loc对应的答案从某一位开始大于ans对应的答案,loc正确
                {
                    ans=loc;
                    break;
                }
                //如果两者每一位对应相等,那么比较长的一个才是正确答案。即ans比较长
            }
        }
    }
    if(str[ans]=='0')
    {
        cout<<0<<endl;
    }else
    {
        not_ok(ans);
        for(i=ans;i<len;i++)
        {
            if(ok[i]==true) //去尾部的0
                break;
            cout<<str[i];
        }
        cout<<endl;
    }
    return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值