题解 | #Kevin翻硬币#

Kevin is Counting Stars

https://ac.nowcoder.com/acm/contest/68258/A

欢迎关注

珂朵莉 牛客周赛专栏

珂朵莉 牛客小白月赛专栏


D. Kevin翻硬币

比赛的时候,一直在猜结论,一共wa了17次,泪目。

但有一个想法,慢慢浮现出现来,比较硬核。

硬核解法

  • 模拟 + 环形差分

先来说下模拟,实际上从原点出发,每次走k步,在环形的n中,一定可以回到原点的。最简单的验证,就是做n次的k步,必然回到原点。

更通俗的数学证明

kx = 0 mod n

gcd(k, n) | 0 必然成立,也就说 x 有解.

根据鹊巢原理,最多走n次,就能回到原点.

为了方便处理,我们把 1-index 转换为 0-index


那剩下的核心问题是:

如何判定是否能够翻转呢?

这个问题可以抽象为,从0点每次走k,然后回到0点的过程中,[0, n - 1]中的每个数的翻转次数都是奇数? 那就一定可以。

假设当前点位t,翻转k,那相当于 [t, t + k - 1] 区间翻转次数整体+1

这里的一个难点,其实环形结构,如何处理这种跨区间的。

比如 [t, t + k - 1], t + k - 1 >= n - 1

那其实可分成两段[t, n - 1], [0, (t + k - 1) % n]做差分

这就是为什么说,环形结构的差分.

最后就是差分的常见累加计算,然后判定[0, n - 1]的数,改变次数都是奇数,那一定可行,否则不行。

import java.io.BufferedInputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.stream.Collectors;

public class Main {

    public static void main(String[] args) {
        Scanner sc = new Scanner(new BufferedInputStream(System.in));
        int t = sc.nextInt();
        while (t-- > 0) {
            int n = sc.nextInt(), k = sc.nextInt();

            // 模拟 + 环形差分
            // 构建每次走k就行,难在于可行解的判定上
            int[] diff = new int[n + 1];
            List<Integer> res = new ArrayList<>();
            int x = 0;
            do {
                res.add(x);
                diff[x]++;
                if (x + k >= n) {
                    // 跨区间,就两段
                    diff[n]--;

                    diff[0]++;
                    diff[(x + k) % n]--;
                } else {
                    diff[x + k]--;
                }
                x = (x + k) % n;
            } while (x != 0);

            // 差分验证, 如果一个数的改变次数是偶数,则无解
            boolean f = true;
            int acc = 0;
            for (int i = 0; i < n; i++) {
                acc += diff[i];
                if (acc % 2 == 0) {
                    f = false;
                    break;
                }
            }

            if (!f) {
                System.out.println(-1);
            } else {
                System.out.println(res.size());
                System.out.println(res.stream().map(y -> String.valueOf(y + 1)).collect(Collectors.joining(" ")));
            }
        }
    }

}
全部评论
diff[n]++有什么用吗
1 回复 分享
发布于 2023-11-07 14:12 四川

相关推荐

01-14 10:23
已编辑
湖南师范大学 计调
太久没更新,前几天看到一条评论,说“牛客就是当年那群做题区毕业了开始找工作还收不住那股味”的群体。字里行间透着居高临下的评判,不是,他该不会以为自己很幽默?很犀利吧?作为在牛客混了不算短日子的用户,我感到的不只是被冒犯,更是一种深刻的悲哀——这种以“松弛感”为名,对另一种生存策略的轻蔑,颇有一种自己考不上大学早早出来混社会,嘲笑考上大学的人是书呆子,然后大言不惭地说:死读书有什么用,人脉和资源才是硬道理。我不知道说这个话的人,手头究竟握着多少真正管用的人脉与资源,也不知道他这么傲慢地说出“那股味”的时候,是站在哪一个巨人的肩膀上,才能如此“松弛从容”地俯视众生,还能品评出别人身上“没收住”的余...
淬月星辉:这种评论把正常的努力扭曲成卷😂,说白了就是自己不努力,看着身边努力的人一个个都事业有成了,自己的心里开始不平衡了,就发这种酸言酸语。牛客可以说是我用过那么多平台里社区氛围最好的论坛了,用了大半年了,基本上没见过有人吵架的,都是在互帮互助提建议,帮忙看简历的,帮忙选offer的,帮忙指点学习路线的,分享工作经验和趣事的,我觉得这才是互联网该有的样子。
点赞 评论 收藏
分享
评论
4
1
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务