『Noi2016十连测第一场 - 模范学长』

pdf版题面 在线提交(需要权限)

题目

问题描述

蒻滋滋是一名实力强大的 OIer 。不久前,他在滋滋国国家队选拔赛过程中突发神题过敏综合征,情况危急,但他坚持回到考场,边做手术边比赛,最终仅以微弱差距不敌某交通工具获得全场第二。为此还被授予了感动滋滋国 OIer 荣誉称号。

在校园里,蒻滋滋是一个乐于助人的模范学长。 whx 小学妹经常来向蒻滋滋请教。前不久, whx 在学习区分奇数和偶数时遇到了困难,便来找蒻滋滋寻求帮助,蒻滋滋不仅和她详细讲解了区分奇数偶数的方法,还一时兴起,给 whx 普及了多项式和行列式的相关知识。

善于思考的 whx 小学妹立马提出了一个问题:给一个$N \times N$的矩阵$A$,$A$的每个元素都是一个整系数多元多项式,现在求出这个矩阵的行列式$|A|$,显然$|A|$也是一个多元多项式。 whx 想知道,把$|A|$合并同类项之后,是否每一项前的系数都是偶数呢?

行列式的定义:$|A| = \sum_{\sigma \in S_N} {\rm sgn}(\sigma) \prod_{i = 1}^{N} A_{i, \sigma(i)}$,其中$S_N$是$N$的所有排列组成的集合,当排列$\sigma$的逆序对数目为偶数时${\rm sgn}(\sigma) = 1$,否则${\rm sgn}(\sigma) = -1$。

输入格式

第一行一个正整数$T$表示数据组数,对于每组数据:

第一行一个正整数$N$表示行列式的阶数。

接下来$N$行,每行$N$个用空格隔开的字符串表示矩阵$A$。

一个字符串表示一个多元多项式,具体表示方法如下:

多项式的每一项用一个包含小写字母或数字的字符串表示,不同的项之间仅用一个‘+’隔开,对于包含数字的项,只可能是常数项“0”或“1”,非常数项是一个小写字母串(不包含数字),一个小写字母出现次数代表了他的次数,项可能重复出现,所以其系数就是出现次数,一个多项式至少有一项(零多项式表示为“0”)。

例如$2ax^2 + pq + 1$可以表示为“1+xax+pq+axx”。

输出格式

对于每组数据输出一行一个单词“Yes”表示每一项前系数都是偶数,“No”表示存在一项的系数不是偶数。

样例输入1

4
1
p+p
2
xx+1 0
0 x
3
x y z
x y z
x y z
orz qaq tat
3
a+b b+c c+a
b+c c+a a+b
ab+bc ac+bc ab+ac

点击这里下载

样例输出1

Yes
No
Yes
Yes

点击这里下载

样例数据1解释

第一个行列式为$2p$,第二个行列式为$x^3 + x$,第三个行列式为$0$,第四个行列式为$2a^2b^2 + 2a^2c^2 + 2b^2c^2 - 2a^2bc - 2ab^2c - 2abc^2$。

样例输入2

点击这里下载

样例输出2

点击这里下载

数据范围与约定

令$len_{i, j}$表示$A_{i, j}$输入字符串的长度。

对于$20\%$的数据:$N \leq 4, len_{i, j} \leq 20$

对于$20\%$的数据:$N \leq 20, A_{i, j} \in \{0, 1, x, 1 + x\}$

对于$100\%$的数据:$T \leq 20, N \leq 50, len_{i, j} \leq 100$,变量个数不超过$26$(所有小写字母)。

题解

(稍后再补)

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <ctime>
#include <cctype>
#include <algorithm>
using namespace std;
#define MAXN 60
#define MAXL 110
const int MOD = 0x2000035;
inline int getrand()
{
int s = 0;
while ((s ^ MOD) > s)
s = (s << 1) | (rand() & 1);
return (s ^ MOD);
}
int T;
int n;
char str[MAXN][MAXN][MAXL];
int data[MAXN][MAXN];
int value[26];
int mul(int a, int b)
{
int s = 0;
while (b)
{
if (b & 1)
s ^= a;
a <<= 1;
if (a > (a ^ MOD))
a ^= MOD;
b >>= 1;
}
return s;
}
int getvalue(int x, int y)
{
int len = strlen(str[x][y]);
char *s = str[x][y];
int r = 0, t = 1;
for (int i = 0; i < len; i++)
{
char c = s[i];
if (c == '+')
{
r ^= t;
t = 1;
}
else if (isalpha(c))
t = mul(t, value[c - 'a']);
else
t = c - '0';
}
return r;
}
bool gauss()
{
for (int i = 0; i < n; i++)
{
int k = -1;
for (int j = i; j < n; j++)
if (data[j][i])
{
k = j;
break;
}
if (k == -1)
return true;
if (i != k)
for (int j = 0; j < n; j++)
swap(data[i][j], data[k][j]);
for (int j = i + 1; j < n; j++)
if (data[j][i])
{
int ls = data[j][i];
for (int k = 0; k < n; k++)
data[j][k] = mul(data[j][k], data[i][i]) ^ mul(data[i][k], ls);
}
}
return false;
}
int main()
{
freopen("rzz.in", "r", stdin);
freopen("rzz.out", "w", stdout);
srand(time(0));
scanf("%d", &T);
while (T--)
{
scanf("%d", &n);
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
{
scanf("%s", str[i][j]);
str[i][j][strlen(str[i][j]) + 1] = 0;
str[i][j][strlen(str[i][j])] = '+';
}
int test;
for (test = 0; test < 5; test++)
{
for (int i = 0; i < 26; i++)
value[i] = getrand();
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
data[i][j] = getvalue(i, j);
if (!gauss())
break;
}
if (test < 5)
printf("No\n");
else
printf("Yes\n");
}
return 0;
}
文章目录
  1. 1. 题目
    1. 1.1. 问题描述
    2. 1.2. 输入格式
    3. 1.3. 输出格式
    4. 1.4. 样例输入1
    5. 1.5. 样例输出1
    6. 1.6. 样例数据1解释
    7. 1.7. 样例输入2
    8. 1.8. 样例输出2
    9. 1.9. 数据范围与约定
  2. 2. 题解
  3. 3. 代码
,