感谢 Misono_Mika 大佬创建的构造题单qwq!
题目链接
题目
题目大意
给出一个质数 和一个长度为 的序列 ,保证对于 ,有 ,试构造一个 的矩阵 ,满足:
- 对于 ,有 。
- 对于 ,有 。
- 对于 ,有 。
思路
假设我们最终构建的矩阵如下图所示。
第二个条件其实是说对任意 ①②③④ 不重合的子矩阵,满足
这个式子直接做没什么头绪,但是可以转化成
这有什么用呢?
我们通过这步转化将条件二变成了“任意两列对应行相减之差对 取余的结果互不相同”。
对 取余一共有 种不同的结果,我们被要求构建的矩阵也恰好 行,所以我们可以构建出如下矩阵:
该矩阵满足条件 ,和条件 。
上面给出的矩阵显然满足条件 ,让我们证明它也满足条件 。
,
我们可以得到
\begin{cases} a_{x_1,y_1}=(x_1-1)\times(y_1-1)\mod n\ a_{x_1,y_2}=(x_1-1)\times(y_2-1)\mod n\ a_{x_2,y_1}=(x_2-1)\times(y_1-1)\mod n\ a_{x_2,y_2}=(x_2-1)\times(y_2-1)\mod n \end{cases}
>
> 所以
> $$
> \begin{aligned}
&a_{x_1,y_1}-a_{x_1,y_2}\\
=&(x_1-1)\times(y_1-1)-(x_1-1)\times(y_2-1)\\
=&(x_1-1)\times(y_1-y_2)\\\\
&a_{x_2,y_1}-a_{x_2,y_2}\\
=&(x_2-1)\times(y_1-1)-(x_2-1)\times(y_2-1)\\
=&(x_2-1)\times(y_1-y_2)\\\\
\end{aligned}
如果 ,
那么
\begin{aligned} (y_1-y_2)\times (x_1-1) &\equiv (x_2-1)\times(y_1-y_2)\pmod n\ (y_1-y_2)\times (x_1-x_2)&\equiv 0\pmod n \end{aligned}
> 即
> $$
\begin{aligned}
(y_1-y_2)\times (x_1-x_2)\mod n&=0\\
((y_1-y_2)\mod n)\times ((x_1-x_2)\mod n)\mod n&=0
\end{aligned}
显然有
0\lt (y_1-y_2)\mod n< n\ 0\lt (x_1-x_2)\mod n< n
>且 $n$ 为质数,所以 $(y_1-y_2)\times (x_1-x_2)$ 不是 $0$ 也不含因数 $n$,即 $(y_1-y_2)\times(x_1-x_2)\mod n=0$ 不可能成立。
>
>与假设矛盾。
>
>所以上述矩阵一定满足条件 $2$。
那么条件 $3$ 该怎么办呢?\
容易发现如果我们有一个满足条件 $1$ 和条件 $2$ 的矩阵,让它的某一行中所有数同时增加 $x$ 再对 $n$ 取余,行内任意两个元素之差不会改变,所以新产生的矩阵也满足条件 $1$ 和条件 $2$。所以我们只需要让刚才构造的矩阵的第 $i$ 行所有数字都加上 $b_i-a_{i,i}$ 再对 $n$ 取余即可。
# 代码
```cpp
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <iostream>
#include <math.h>
#include <map>
#include <queue>
#include <vector>
#include <stdlib.h>
#include <time.h>
using namespace std;
using LL=long long;
const int N=351;
int n,m,k,a[N],b;
LL solve()
{
scanf("%d",&n);
for (int i=1;i<=n;++i)
{
scanf("%d",&b);
a[1]=0;
for (int j=2;j<=n;++j) a[j]=(a[j-1]+i-1)%n;
int dt=b-a[i];
for (int j=1;j<=n;++j) printf("%d ",(a[j]+n+dt)%n);
printf("\n");
}
return 0;
}
int main()
{
int T=1;
while (T--) solve();
return 0;
}
```