【QED】勇敢者的游戏Ⅰ

题目描述

“mytx”和“锕狗”在玩一种很新的游戏,游戏规则如下。

每一轮游戏中,游戏系统会随机生成 m m m n n n 两个数,然后生成 m ( 1 ≤ m ≤ 1000 ) m(1 \leq m \leq 1000) m(1m1000) 个空格,并随机选定其中的 n ( 0 ≤ n ≤ m ) n(0 \leq n \leq m) n(0nm) 个空格,在每个空格上分别独立地随机生成一个整数以填充该空格,这些数字的范围在 [ 0 , 9 ] [0, 9] [0,9]之内。

接下来轮到玩家操作。

若仍剩下未被系统填充的空格,则对于这 m − n m-n mn 个空格,mytx需要在每个空格里都填上一个整数,但这些数字没有范围上的要求,mytx可以挑选对他最有利的策略来进行填空。待mytx填写完毕后,锕狗需要尝试寻找连续的 x x x 个空格 ( 1 ≤ x ≤ m ) (1 \leq x \leq m) (1xm),使得这些空格内的数之和是 m m m 的整数倍。若锕狗能找到这样的若干个空格,则该轮游戏中锕狗获胜,他得 1 1 1分。反之,mytx得 1 1 1分。

现在你分别已知每一轮游戏中 m m m n n n 的大小,且预先告诉你系统会在哪些空格中生成哪些数,也即你预先知道在每一轮中轮到玩家操作时,空格序列的状况是如何的。现在请你解决这样一个问题:若假设mytx和锕狗都足够聪明,会选择对自己而言最有利的游戏策略,那么在经过 t ( 1 ≤ t ≤ 1000 ) t(1 \leq t \leq 1000) t(1t1000)轮游戏后,他们两个之间的比分将会是多少?

据说这是一个只有勇敢者才能解决的问题。

输入格式

第一行一个整数 t t t,代表游戏的轮数。

接下来 2 t 2t 2t 行,相邻的 2 2 2行为一组,共 t t t 组。每一组中,第一行有两个以空格分隔的整数,分别代表该轮游戏中的 m m m n n n ;第二行中有以空格分隔的 m m m 个字符,代表轮到玩家操作时,空格序列的状况。

其中英文字符 “  ?  ” “\ ?\ ”  ?  代表一个未被填充的空格,其余数字字符 ( “  0  ” ∼ “  9  ” ) (“\ 0\ ” \sim “\ 9\ ”) ( 0  9 )代表一个已被填充的空格,用以表示其中的数。

输入数据不含行末空格和文末空行。

输出格式

输出仅一行。以mytx比锕狗的顺序输出两人的比分,中间用英文冒号 “ : ” “:” :隔开。

测试样例

2
7 3
5 ? ? 7 ? 0 ?
5 5
2 2 1 6 2
0:2

样例说明

游戏共进行了 2 2 2轮。

第一轮中,系统在 7 7 7个空格中的 3 3 3个填充了数字,但无论mytx如何填写剩余的空格,锕狗总可以选取第 4 4 4个空格(其中填充了 7 7 7),使得所选的连续的空格内的数之和 7 7 7 7 7 7的整数倍。同理,锕狗也可以选取第 6 6 6个空格(其中填充了 0 0 0),使得所选的连续的空格内的数之和 0 0 0 7 7 7的整数倍。故该轮游戏锕狗得 1 1 1分。

第二轮中,系统在 5 5 5个空格中的全部 5 5 5个都填充了数字,mytx无法继续填写。锕狗可以选取第 1 、 2 、 3 1、2、3 123个空格,使得所选的连续的空格内的数之和 2 + 2 + 1 = 5 2+2+1=5 2+2+1=5 5 5 5的倍数。故该轮游戏锕狗得 1 1 1分。请注意,尽管第 1 、 2 、 4 1、2、4 124个空格中的数之和 2 + 2 + 6 = 10 2+2+6=10 2+2+6=10 5 5 5的倍数,但锕狗不可以选取这三个空格进行求和,因为它们并不连续。

综上所述,总比分为 0 : 2 0:2 0:2

数据范围

1 ≤ t ≤ 1000 1 \leq t \leq 1000 1t1000

1 ≤ m ≤ 1000 1 \leq m \leq 1000 1m1000


思路

这道题目其实简单尝试之后很容易就能发现:好像无论怎么样尝试最后都是锕狗赢,锕狗关了吧没意思 ,事实上也确实是这样,比赛的时候建议直接莽一发,这里我个人认为可以这样证明:

假设有一个数组 A A A,包含 m m m 个整数,我们想找到连续 x x x 个数的和是 m m m 的整数倍。

首先,让 S ( i ) S(i) S(i) 表示从数组的开头到第 i i i 个元素的累加和。如果存在两个索引 i i i j j j,使得 S ( j ) S(j) S(j) S ( i ) S(i) S(i) 除以 m m m 得到的余数相同,即 ( S ( j ) − S ( i ) ) m o d ( m ) = 0 (S(j) - S(i)) mod (m) = 0 (S(j)S(i))mod(m)=0,那么这意味着数组中索引 i i i j j j 之间的元素和是 m m m 的整数倍。

这基于以下原理:假设 S ( j ) S(j) S(j) S ( i ) S(i) S(i) 除以 m m m 得到相同的余数,那么 ( S ( j ) − S ( i ) ) (S(j) - S(i)) (S(j)S(i)) 一定是 m m m 的倍数。而 ( S ( j ) − S ( i ) ) (S(j)- S(i)) (S(j)S(i)) 就是数组索引 i i i j j j 之间元素的和,即存在一个连续子数组的和是 m m m 的整数倍。

所以问题变成了:证明数组中存在两个索引 i i i j j j,使得 S ( j ) S(j) S(j) S ( i ) S(i) S(i) 除以 m m m 得到相同的余数。

这个问题可以通过抽屉原理来理解:假设有 m m m 个前缀和 S ( i ) m o d ( m ) ( 0 < i < m ) S(i) mod (m)(0 < i < m) S(i)mod(m)0<i<m,而这些前缀和的取值范围是 ( 0 , m ) (0,m) (0,m)。那么根据抽屉原理,必然存在两个前缀和 S ( i ) S(i) S(i) S ( j ) S(j) S(j) 满足 S ( i ) m o d ( m ) = S ( j ) m o d ( m ) S(i) mod (m) = S(j) mod (m) S(i)mod(m)=S(j)mod(m),即它们的余数相同。(为什么不考虑 S ( i ) = 0 S(i)=0 S(i)=0的情况呢?那不就是这一串数字和是 m m m的倍数咧)

因此,通过抽屉原理和前缀和的思想,可以证明在包含 m m m 个数字的数组中,存在连续 x ( 1 < = x < = m ) x(1<=x<=m) x1<=x<=m个数的和是 m m m的整数倍。

核心代码

#include <bits/stdc++.h>
#define debug(x) cout<<#x<<" = "<<x<<"\n"
using namespace std;

int main() {
    int n;
    cin>>n;
    printf("0:%d\n",n);
    return 0;
}
  • 23
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

想要AC的dly

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值