题目描述
“mytx”和“锕狗”在玩一种很新的游戏,游戏规则如下。
每一轮游戏中,游戏系统会随机生成 m m m、 n n n 两个数,然后生成 m ( 1 ≤ m ≤ 1000 ) m(1 \leq m \leq 1000) m(1≤m≤1000) 个空格,并随机选定其中的 n ( 0 ≤ n ≤ m ) n(0 \leq n \leq m) n(0≤n≤m) 个空格,在每个空格上分别独立地随机生成一个整数以填充该空格,这些数字的范围在 [ 0 , 9 ] [0, 9] [0,9]之内。
接下来轮到玩家操作。
若仍剩下未被系统填充的空格,则对于这 m − n m-n m−n 个空格,mytx需要在每个空格里都填上一个整数,但这些数字没有范围上的要求,mytx可以挑选对他最有利的策略来进行填空。待mytx填写完毕后,锕狗需要尝试寻找连续的 x x x 个空格 ( 1 ≤ x ≤ m ) (1 \leq x \leq m) (1≤x≤m),使得这些空格内的数之和是 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(1≤t≤1000)轮游戏后,他们两个之间的比分将会是多少?
据说这是一个只有勇敢者才能解决的问题。
输入格式
第一行一个整数 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 1、2、3个空格,使得所选的连续的空格内的数之和 2 + 2 + 1 = 5 2+2+1=5 2+2+1=5是 5 5 5的倍数。故该轮游戏锕狗得 1 1 1分。请注意,尽管第 1 、 2 、 4 1、2、4 1、2、4个空格中的数之和 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 1≤t≤1000
1 ≤ m ≤ 1000 1 \leq m \leq 1000 1≤m≤1000
思路
这道题目其实简单尝试之后很容易就能发现:好像无论怎么样尝试最后都是锕狗赢,锕狗关了吧没意思 ,事实上也确实是这样,比赛的时候建议直接莽一发,这里我个人认为可以这样证明:
假设有一个数组 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) x(1<=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;
}