首页 > 其他分享 >CF1804C 题解

CF1804C 题解

时间:2023-03-19 22:15:26浏览次数:51  
标签:格子 int 题解 转动 leq 枚举 CF1804C 转盘

题目链接

今天好不容易有空更那就再更一篇(

一道很有意思的诈骗题,我会写出我的思考过程。

题意:(我的翻译)

一个转盘有 $n$ 个格子分别为 $0$ $1$ $2$ $\cdots$ $n-1$,初始时在 $x$ 号格子,你希望转动一次转盘来使它回到 $0$ 号位置,(转盘转到 $n-1$ 后再转就会回到 $0$)。

你有一个可以使出的最大力气 $p$,你可以使出任意的力气 $f$ 满足 $f\leq p$。然后,转盘会转动 $f$ 秒,第一秒转动 $f$ 个格子,第二秒转动 $f-1$ 个格子,以此类推,第 $f$ 秒就会转动 $1$ 个格子,之后转盘就会停止转动。

现在给你 $n$,$x$,$p$,请你判断能否使出一次一个力气 $f$,使得转盘能够转到 $0$ 号格子,$T$ 组数据,用 ``No`` 和 ``Yes`` 回答

数据范围:

$1\leq T\leq 10^4$

单组数据中 $n\leq 10^5$

所有数据中 $n$ 之和小于 $2\times 10^5$

$1\leq p\leq 10^9$

思路

首先想到枚举花多少力气,我们可以尝试这样枚举。$i$ 从 $1$ 枚举到 $p$,每一轮多转 $i$ 格。容易得出,转 $i$ 下时,转盘总共了 $1+2+\cdots +i$ 格,和使出 $i$ 的力气的效果相同。

推论 $1$:(显然成立)转 $i$ 格和转 $i \% n$ 的效果相同。

再来看刚刚枚举 $i=1\cdots p$ 的过程,假设 $n<p$,我们就可以发现这个枚举过程化简为了这样。转 $1$ 格,转 $2$ 格 $\cdots$ 转 $n-1$ 格,转 $n$ 格相当于转 0 格没用,所以转 $n+1$ 格,也就是再转 $1$ 格。

枚举过程变成了一个循环节,长度为 $n-1$,第 $i$ 项为 $i$,使用等差数列求和公式得一个循环节使转盘转动 $\frac{n\times (n-1)}{2}$ 格。

分类讨论,当 $n$ 为奇数时,我们发现一个循环节使转盘的转动效果为 $0$ 格,所以只要转动一个循环节,看看行不行即可。(注:此时转动 $i$ 个循环节再转 $j$ 下就相当于转 $j$ 下)

当 $n$ 为偶数时,我们发现一个循环节使转盘转动 $\frac{n}{2}$ 格,两个循环节就会使转盘转动 $0$ 格,所以只要枚举到两个循环节看下行不行即可。

因为是赛时代码有点慌所以稍乱:

#include <cmath>
#include <iostream>
#define int long long
using namespace std;
int t, n, x, p;
int sum, tmp;
signed main () {
    cin >> t;
    while (t --) {
        cin >> n >> x >> p;
        tmp = (1LL + n) * n / 2;
        if (n & 1) {
            bool f = false;
            for (int i = 1; i <= min (n, p); i ++) {
                if ( (x + i * (i + 1LL) / 2) % n == 0) {
                    f = true;
                    break;
                }
            }
            if (!f) cout << "No" << "\n";
            else cout << "Yes" << "\n";
        }
        else {
            bool f = false;
            for (int i = 1; i <= min (n, p); i ++) {
                if ( (x + i * (i + 1LL) / 2) % n == 0) {
                    f = true;
                    break;
                }
            }
            if (p > n) {
                p -= n;
                if (x >= n / 2) x -= n / 2;
                else x += n / 2;
                for (int i = 1; i <= min (n, p); i ++) {
                    if ( (x + i * (i + 1) / 2) % n == 0) {
                        f = true;
                        break;
                    }
                }
            }
            if (!f) cout << "No" << "\n";
            else cout << "Yes" << "\n";
        }
    }
    return 0;
}

 

标签:格子,int,题解,转动,leq,枚举,CF1804C,转盘
From: https://www.cnblogs.com/Xy-top/p/17234504.html

相关文章

  • 【题解】ABC294
    AtCoderBeginnerContest294AFilter无意义题,找出所有偶数。BASCIIArt无意义题,按题意模拟。CMergeSequences无意义题,离散化即可。DBank无意义题,set维护即......
  • ucyhf 题解
    题目传送门愚人节题目,具体题面看翻译。先写一个判断素数的函数,这题并不需要什么特殊的筛法,新手可以参考以下代码。boolisprime(intx){if(x<=1)return0;......
  • Party 题解
    题目传送门一道简单的并查集练手题。与普通的并查集不同,除此之外还需记录下来某两人的讨厌关系,使得他们不能在同一集合中。if(find_root(x)==find_root(y))vis[find......
  • CF1060E 题解
    前言题目传送门!更好的阅读体验?提供一种更加麻烦的换根DP写法。思路代码#include<iostream>#include<cstdio>usingnamespacestd;typedeflonglongll;cons......
  • 3 月 15 日测试题解
    3月15日测试题解这学校的评测机我是真的吐了,\(\text{380pts}\rightarrow\text{300pts}\),电脑速度跟BZOJ有的一拼。一句话总结:简单,过于简单,但是在练习读题能力上十......
  • 3 月 19 日测试题解
    3月19日测试题解原来这就是AK的滋味吗,不过,我却完全没感到开心呢。T1题意给出两个整数\(a\),\(b\),重复以下操作直到\(a=b\):设\(a>b\),否则交换\(a\)与\(......
  • P5445 [APIO2019] 路灯 题解
    题目链接题目描述给你一个01串,有\(q\)个时刻,每个时刻要么把一位取反,要么问你在过去的所有时刻中有多少个时刻\(a\)和\(b-1\)之间都为1。题目分析观察题目,我们......
  • 2023.3.19 模拟赛题解
    银行取款题意在现代文明社会中,大家在诸如银行办理业务、车站买票等活动时都很文明,没有插队的现象,本着"先来先服务"的规矩。初赛已经结束了,凡凡的爸爸打算上银行去取点......
  • 【问题解决】Linux 下 VSCode IntelliSense 对 C 语言读写锁类型报错的问题
    如图下图所示,当我们想要使用C语言读写锁类型时,IntelliSense会提示如下未定义的错误:IntelliSense提示错误但是,如果忽略这些错误,直接`gcc-o`程序又没有问题。通......
  • 题解:【ARC112C】 DFS Game
    题目链接题目里面的注意点还是很多的,如果读错了题整个思路可能会一点都不对。首先是移动和选取硬币的操作是分开的,所以你移动到了一个有硬币的节点,将是你的对手获得硬币。......