Codeforces Round #770 (Div. 2) ABCD题解

A. Reverse and Concatenate

思路
答 案 要 么 1 要 么 2 答案要么1要么2 12
等 于 1 的 必 要 条 件 是 反 转 之 后 是 它 本 身 等于1的必要条件是反转之后是它本身 1
反 之 就 是 2 反之就是2 2
时间复杂度 O n On On

#define sf(x) scanf("%d",&x)
#define all(x) (x).begin(),(x).end()
#define cf int _; cin>> _; while(_--)
inline void sf2(int &a , int &b) { sf(a) , sf(b) ;}
signed main()
{
    cf
    {
        int n , m ;
        sf2(n, m);
        
        string s;
        cin >> s;
 
        string ans = s;
        reverse(all(s));
 
        if (s != ans && m)
            puts("2");
        else
            puts("1");
    }
    return 0;
}

B. Fortune Telling

思路
注 意 到 x 和 x + 3 奇 偶 性 不 同 注意到x和x+3奇偶性不同 xx+3

如 果 a 是 奇 数 , b 是 偶 数 如果a是奇数,b是偶数 ab
假 设 x 是 奇 数 假设x是奇数 x
a + = x 是 偶 数 a+=x是偶数 a+=x
b + = x 是 奇 数 b+=x是奇数 b+=x
a ⊕ = x 是 偶 数 a\oplus=x是偶数 a=x
b ⊕ = x 是 奇 数 b\oplus=x是奇数 b=x
x 是 偶 数 同 理 x是偶数同理 x

我 们 发 现 a 和 b 的 奇 偶 性 一 直 是 相 对 的 我们发现a和b的奇偶性一直是相对的 ab
如 果 x 是 偶 数 a b 奇 偶 性 不 变 如果x是偶数ab奇偶性不变 xab
如 果 x 是 奇 数 a b 奇 偶 性 交 换 如果x是奇数ab奇偶性交换 xab

题 目 最 后 一 句 话 题目最后一句话
exactly one of your friends could have actually gotten that number.
说 明 答 案 必 定 存 在 说明答案必定存在
所 以 统 计 奇 数 个 数 即 可 所以统计奇数个数即可

说 点 题 外 话 , 奇 偶 性 这 个 性 质 c f 经 常 考 , 可 以 多 做 做 类 似 的 题 说点题外话,奇偶性这个性质cf经常考,可以多做做类似的题 cf
时间复杂度 O n On On

#define fer(i,a,b) for(int i = a ; i <= b ; ++ i)
#define cf int _; cin>> _; while(_--)
const int N = 1e6 + 10 ;
int n ;
int a[N] , x , y ;
 
signed main()
{
    cf
    {
        cin >> n >> x >> y ;
        
        int cnt = 0 ;
        fer(i,1,n)
        {
            sf(a[i]) ;
            if(a[i] & 1) cnt ++ ;
        }
        
        if(x & 1)
        {
            if(y & 1)
            {
                if(cnt % 2 == 0) puts("Alice") ;
                else puts("Bob") ;
            }
            else
            {
                if(cnt % 2) puts("Alice") ;
                else puts("Bob") ;
            }
        }
        else 
        {
            if(y & 1)
            {
                if(cnt % 2 == 0) puts("Bob") ;
                else puts("Alice") ;
            }
            else
            {
                if(cnt % 2) puts("Bob") ;
                else puts("Alice") ;
            }
        }
    }
    return 0;
}

C. OKEA

思路
n 是 偶 数 或 者 k < = 1 可 以 , 否 则 都 不 可 以 n是偶数或者k<=1可以,否则都不可以 nk<=1
时间复杂度 O n k Onk Onk

#define fer(i,a,b) for(int i = a ; i <= b ; ++ i)
#define cf int _; cin>> _; while(_--)
signed main()
{
    cf
    {
        int n , k ;
        cin >> n >> k ;
        
        if(n % 2 == 0)
        {
            puts("YES") ;
            
            int cnt = 0 ;
            for(int i = 1 ; i <= n * k ; i += 2)
            {
                cnt ++ ;
                cout << i << " " ;
                if(cnt == k)
                {
                    cnt = 0 ;
                    puts("") ;
                }
            }
            for(int i = 2 ; i <= n * k ; i += 2)
            {
                cnt ++ ;
                cout << i << " " ;
                if(cnt == k)
                {
                    cnt = 0 ;
                    puts("") ;
                }
            }
        }
        else if(k <= 1)
        {
            puts("YES") ;
            if(k == 1)
            {
                fer(i,1,n*k)
                {
                    cout << i << "\n" ;
                }
            }
        }
        else puts("NO") ;
    }
    return 0;
}

D. Finding Zero

思路
没 错 , d 题 想 了 快 2 h 才 做 出 来 没错,d题想了快2h才做出来 ,d2h
有 个 超 级 超 级 重 要 的 性 质 有个超级超级重要的性质
经 过 了 漫 长 时 间 的 思 考 以 及 草 稿 纸 上 的 举 不 出 反 例 才 得 到 的 结 果 经过了漫长时间的思考以及草稿纸上的举不出反例才得到的结果 稿

第 一 次 假 设 三 个 数 a [ x ] , a [ y ] , a [ z ] 的 下 标 是 1 , 2 , 3 第一次假设三个数a[x],a[y],a[z]的下标是1,2,3 a[x],a[y],a[z]1,2,3

假 设 当 前 差 值 为 l a s t 假设当前差值为last last
差 值 就 是 最 大 值 − 最 小 值 , 也 就 是 询 问 x , y , z 的 结 果 差值就是最大值-最小值,也就是询问x,y,z的结果 ,x,y,z

做 2 次 循 环 做2次循环 2
第 一 次 用 4 到 n 的 每 一 个 数 去 替 换 掉 第 三 个 数 第一次用4到n的每一个数去替换掉第三个数 4n
如 果 当 前 差 值 大 于 等 于 > = l a s t 如果当前差值大于等于>=last >=last
就 替 换 掉 第 三 个 数 , 同 时 更 新 l a s t = 当 前 差 值 , 否 则 不 替 换 就替换掉第三个数,同时更新last=当前差值,否则不替换 ,last=,

同 理 , 第 二 次 循 环 替 换 掉 第 二 个 数 同理,第二次循环替换掉第二个数
同 时 更 新 l a s t 同时更新last last

两 次 循 环 之 后 , a [ x ] , a [ y ] , a [ z ] 必 定 存 在 0 和 当 前 数 组 中 的 最 大 值 两次循环之后,a[x],a[y],a[z]必定存在0和当前数组中的最大值 ,a[x],a[y],a[z]0
那 怎 么 找 到 0 和 最 大 值 呢 那怎么找到0和最大值呢 0
有 个 逻 辑 是 这 样 的 , 你 找 另 外 一 个 下 标 i d 有个逻辑是这样的,你找另外一个下标id ,id

询 问 i d , y , z 的 结 果 询问id,y,z的结果 id,y,z
如 果 当 前 差 值 = l a s t , 说 明 a [ x ] 一 定 不 是 0 , 那 么 输 出 y , z 即 可 如果当前差值=last,说明a[x]一定不是0,那么输出y,z即可 =last,a[x]0,y,z

同 理 当 前 差 值 ! = l a s t , 那 就 用 i d 替 换 y / z 同理当前差值!=last,那就用id替换y/z !=last,idy/z

题 外 话 题外话
一 开 始 的 三 个 数 的 下 标 不 一 定 非 得 是 1 , 2 , 3 , 任 意 三 个 不 同 的 下 标 都 可 一开始的三个数的下标不一定非得是1,2,3,任意三个不同的下标都可 1,2,3,
两 次 循 环 不 一 定 非 得 替 换 第 二 个 数 和 第 三 个 数 , 任 意 2 个 数 皆 可 两次循环不一定非得替换第二个数和第三个数,任意2个数皆可 2
这 个 性 质 可 以 在 草 稿 纸 上 仔 细 想 想 推 敲 推 敲 这个性质可以在草稿纸上仔细想想推敲推敲 稿
个 人 觉 得 举 不 出 来 反 例 在 算 法 竞 赛 当 中 往 往 是 较 为 正 确 的 证 明 个人觉得举不出来反例在算法竞赛当中往往是较为正确的证明
时间复杂度 O n 2 On^2 On2

#define cf int _; cin>> _; while(_--)
signed main()
{
    cf
    {
        int n ;
        cin >> n ;
        
        int x = 1 , y = 2 , z = 3 ;
        int last ;
        
        cout << "? " << x << " " << y << " " << z << '\n' ;
        cout.flush() ;
        
        cin >> last ;
        
        for(int i = 4 ; i <= n ; i ++)
        {
            cout << "? " << x << " " << y << " " << i << '\n' ;
            cout.flush() ;
            
            int k ;
            cin >> k ;
            
            if(k >= last)
            {
                last = k ;
                z = i ;
            }
        }
        
        for(int i = 1 ; i <= n ; i ++)
        {
            if(i == x || i == y || i == z) continue ;
            
            cout << "? " << x << " " << i << " " << z << '\n' ;
            cout.flush() ;
            
            int k ;
            cin >> k ;
            
            if(k >= last)
            {
                last = k ;
                y = i ;
            }
        }
        
        int id = -1 ;
        for(int i = 1 ; i <= n ; i ++)
        {
            if(i == x || i == y || i == z) continue ;
            
            id = i ;
            break ;
        }
        
        int k ;
        cout << "? " << id << " " << y << " " << z << '\n' ;
        cout.flush() ;
        cin >> k ;
        
        if(k == last)
        {
            cout << "! " << y << " " << z << "\n" ;
        }
        else 
        {
            cout << "? " << x << " " << id << " " << z << '\n' ;
            cout.flush() ;
            cin >> k ;
            
            if(k == last)
            {
                cout << "! " << x << " " << z << "\n" ;
            }
            else
            {
                cout << "? " << x << " " << y << " " << id << '\n' ;
                cout.flush() ;
                cin >> k ;
                if(k == last)
                {
                    cout << "! " << x << " " << y << "\n" ;
                }
                else cout << "! " << x << " " << y << "\n" ;
            }
        }
    }
    return 0;
}
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值