2017年8月12日提高组T1 YMW的杯子

本文探讨了一个关于通过每次翻转m个杯子来实现所有杯子从正面朝上变为正面朝下的问题,并提供了一种通过深度优先搜索加记忆化的解决方案。文章还讨论了翻转次数与杯子数量之间的数学关系。

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

Description


有一天YMW看见竞赛室里面放着n个正面向上的杯子,他随手把所有的杯子翻转成正面向下的杯子了。后来突然想起来自己有两只手,于是他尝试同时翻转两只杯子,看下最后能不能翻转成为全部正面朝下。聪明的你看到了这一切,突然脑子里面闪过一个问题,假如每次同时翻转m只杯子,最后能全部翻转成为正面朝下吗?(初始时全部正面朝上)

Input


多组数据,每组数据两个数n和m,以-1,-1结尾

Output


对于每组数据,如果可以输出Yes,不能输出No

Hint


Data Limit:
不少于5组数据,不超过20组数据
对于30%的数据n<=10,m<=5
对于70%的数据n<=100,m<=30
对于100%的数据n<=10000,m<=500

每个输入文件中n和m有一定梯度和差别,保证每个输入中不全为Yes或No

Source


BY BPM

Solution


水题,可耻地因为大小写问题wa了

暴力dfs,观察到翻转的顺序无关,状态只和正面/反面的数量有关,那么搜索+记忆化就可以了

考虑找规律。不难发现若要n个水杯全翻面,则每个杯子需要翻转奇数次。对于偶数n任意m都能满足,对于奇数n只有奇数m能满足。

Code


#include <stdio.h>
#include <string.h>
#define rep(i, st, ed) for (int i = st; i <= ed; i += 1)
#define min(x, y) (x)<(y)?(x):(y)
#define N 12001
int v[N];
bool flag;
inline void dfs(int z, int m, int n){
    if (v[z]){return ;}
    if (z == 0 || flag){
        flag = true;
        return ;
    }
    v[z] = 1;
    int lim = min(z, m);
    rep(i, 1, lim){
        if (m - i <= n - z){
            dfs(z - i + m - i, m, n);
        }
    }
    lim = min(n - z, m);
    rep(i, 1, lim){
        if (m - i <= z){
            dfs(z + i - m + i, m, n);
        }
    }
}
int main(void){
    int n, m;
    while (~scanf("%d %d", &n, &m)){
        memset(v, 0, sizeof(v));
        if (n == -1 && m == -1){break;}
        if (n % m == 0){
            puts("Yes");
            continue;
        }
        flag = false;
        dfs(n, m, n);
        if (flag){
            puts("Yes");
        }else{
            puts("No");
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值