专栏文章
题解:P13776 「o.OI R2」Easy ver.
P13776题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mio85vgg
- 此快照首次捕获于
- 2025/12/02 14:56 3 个月前
- 此快照最后确认于
- 2025/12/02 14:56 3 个月前
表示异或。
先说赛时思路,后面是结论和证明,前面可以跳过。
赛时思路
题目的“连通块”有点抽象,其实就是连通的一块啦,和权值无关。
先分析样例。
第一个样例是一行八列,那么连通块必然是一个子段。所以假设从左往右是 ,那么有 。
根据异或的性质,我们有 ,也就是 。所以根据 就可以确定 ,然后 确定所有数字。对于任意 都是合法的,所以答案是 。
第二个样例是 ,连通块大小为 。直觉上因为大小为 的连通块形状太自由了,所以所有数字都是一样的。证明一下?如果有这样一个形状
PLAINTEXTa b c
d e f
g h i
选择 和 可以知道 ,相应地 ,所以外圈全部相等。然后选择 和 可以知道 ,所以所有的都相等。
那么用 显然可以证明 。证毕。
而所有数字都一样, 又是奇数,奇数个 异或还是 ,所以一定是全是 。所以只有一种可能。
样例 ? 一眼看过去就小于 ,所以相当于没有限制,答案是 ,要对 取模。
这些故事样例告诉我们一些道理结论:
- 答案是 ;
- 虽然没说但是考虑一下 答案是 ,自证不难;以下讨论都不包含上面的两种情况。
- 或 答案是 。
- 答案很可能是 或 ,当 是奇数的时候是 ,偶数是 。
如果最后的结论是正确的那么这题就做完了!赛时想了想挺对的,感觉证明挺麻烦就交上去过了(WA 了一发,因为没开
long long)。但是我们要在这里进行一个证明(赛时没证)。证明
证明的思路是,证明在某个区域内所有数字都相同。第一个思路是模仿样例 ,考虑 ,实际上这样并不是很行,因为 可能大于 。但是其实这样做是有普适性的,所以我们不必使用 这个数字,我们可以使用 ,不管先要证明 ,不然不好做。很简单但是直接做会有问题, 证不了全相同,但是可以证明全是 。
不妨设 ,首先考虑 。显然全是 ,答案是 。然后考虑 的情况。显然可以横竖交叉证明 全相同,然后显然易证 可以。
然后的思路是,填满它。
若 ,则我们从上到下,从左到右填 个
PLAINTEXTX。把其中一个替换为 O,然后在它右边紧贴着的地方填一个 U(因为 ,所以必然可以填上 U):XXXXXXXXX
XXXXXXXXX
XXXXXXXX
XXXOXXXX
XXXXXXXXU
XXXXXXXX
X+O 是连通的,X+U 也是连通的,所以 。只要 O 和 U 不相邻就可以这么干(有一种特殊情况就是相邻也可以这么干但是我们不用管它)。所以选定一个 U 我们就能够证明长方形的所有部分除了和 U 直接相连的那个格子之外都是一样的。又 ,所以至少有 个这样的不同的信息,所以所有 X 都相同。这样我们知道了所有行中数字都是一样的,相应地交换 ,可以知道所有列也都是一样的,故所有数字相同,证毕!
代码实现&提交记录
可可爱爱的赛时代码。
CPP/*
样例 1:
????????
k=6
那么
123456
234567
345678
xor=0
也就是说
1=7
2=8
那么自由度为 6
然而给定了 12345 就能推断出 6,7,8
所以自由度为 5
输出 32
样例 2:
?????
?????
?????
?????
?????
k=5
可以推断出所有数字均相同
而 k 为奇数
所以是 1
样例 3:
看起来很唬人,实际上 114*514<1919810
所以是 2^(114*514) mod 1e9+7
那么?
不妨假设 nm>=k,n<=m
若 nm=k:答案为 2^(nm-1)
若 n=1:长条形,这样答案是容易计算的,容易发现 1&k+1,2&k+2,... 是相同的,然后 k 也不是自由的,所以答案为 2^(k-1)。
若 n>1:应该是可以推出所有数字相同的,那么 k 为奇数的时候是 1,偶数是 2
嗯我猜结论是对的。
*/
/*
好吧,炸了,6。
不过 subtask 0,1,2 是对的
3,4 不对
说明 n=1 讨论是对的
nm=k 草忘了写了
还有没开 long long
wssb
*/
#include <cstdio>
#include <algorithm>
using namespace std;
long long qpow(long long x, long long y)
{
if(y == 0) return 1;
if(y == 1) return x % 1000000007;
long long res = qpow(x, y >> 1);
res = res * res % 1000000007;
if(y & 1) res = res * x % 1000000007;
return res;
}
int main()
{
int t;
scanf("%d", &t);
while(t--)
{
int n, m, k;
scanf("%d%d%d", &n, &m, &k);
if(n > m) swap(n, m);
if(1ll*n*m < k) printf("%lld\n", qpow(2, 1ll*n*m));
else if(1ll*n*m == k) printf("%lld\n", qpow(2, 1ll*n*m-1));
else if(n == 1) printf("%lld\n", qpow(2, k-1));
else printf("%lld\n", (k & 1) ? 1 : 2);
}
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...