AT_agc064_e [AGC064E] Cross Sum Construction题解
[AGC064E] Cross Sum Construction
题目大意
给定
题目分析
由于
首先,由于
令
所以
- 若
\forall 1\le i,j\le n,\left(r_i+c_j\right)\left(2n-1\right)\equiv 2sum\pmod{n-1} 则:
- 若
\forall 1\le i,j\le n,r_i\equiv r_j,c_i\equiv c_j\pmod{n-1} ,则:
所以
考虑如何使得
-
当
n\bmod 2=1 时,可以借助溢出转变下标奇偶性来处理,令s_{i,j}=A_{-i+j}+B_{-2i+j} ,此时r_x=c_x=\sum_{i=1}^{n}A_i+B_i 。 -
当
n\bmod 2=0 时,设s_{i,j}=A_l+B_k ,先考虑k ,当i,j 改变时,k 需要不重不漏,可以构造出k=\begin{cases}-i+j&-i+j\ne 0\text{ 且}-i+j\ne\frac{n}{2}\\\frac{n\times\left(i\bmod2\right)}{2}&-i+j=0\text{ 或}-i+j=\frac{n}{2}\end{cases} ,再考虑l ,可以发现直接通过i,j 算出l 是困难的,可以反过来,从l 反推i,j ,分别从0\sim n-1 枚举l 和x ,令\left(i,j\right)=\begin{cases}\left(2\times\left\lfloor\frac{l}{2}\right\rfloor+\frac{n\times\left(l\bmod2\right)}{2}+x,2\times\left\lfloor\frac{l}{2}\right\rfloor+2x\right)&x=0\sim\frac{n}{2}-1\\\left(2\times\left\lfloor\frac{l}{2}\right\rfloor+\frac{n\times\left(l\bmod2\right)}{2}+x,2\times\left\lfloor\frac{l}{2}\right\rfloor+2x+1\right)&x=\frac{n}{2}\sim n-1\end{cases} ,此时r_x=c_x=\sum_{i=1}^{n}A_i+B_i (具体证明可以看官方题解)。
这样就解决了
时间复杂度
代码
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 510;
int t, n;
ll s[N][N], sum, r[N], c[N], cnt[N], a[N], b[N];
void solve()
{
cin >> n;
sum = 0;
for (int i = 0; i < n; i++) {
r[i] = c[i] = 0;
}
for (int i = 0; i < n; i++) {
cin >> a[i];
}
for (int i = 0; i < n; i++) {
cin >> b[i];
}
if (n == 1) {
cout << a[0] + b[0] << '\n';
return;
}
if (n % 2) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
s[i][j] = a[(n + j - i) % n] + b[(2 * n - 2 * i + j) % n];
}
}
} else {
for (int i = 0; i < n - 1; i++) {
cnt[i] = -1;
}
for (int i = 0; i < n; i++) {
if (cnt[(n - 1 + a[i] % (n - 1)) % (n - 1)] != -1) {
swap(a[cnt[(n - 1 + a[i] % (n - 1)) % (n - 1)]], a[0]);
swap(a[i], a[n / 2]);
break;
}
cnt[(n - 1 + a[i] % (n - 1)) % (n - 1)] = i;
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (i == j || (n + j - i) % n == n / 2) {
s[i][j] = a[(i % 2) * n / 2];
} else {
s[i][j] = a[(n + j - i) % n];
}
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
int x = (2 * (i / 2) + (i % 2) * n / 2 + j) % n, y = (2 * (i / 2) + 2 * j + (j >= n / 2)) % n;
s[x][y] += b[i];
}
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
sum += s[i][j];
}
}
while (sum % (2 * n - 1)) {
s[0][0] += n - 1;
sum += n - 1;
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
r[i] += s[i][j];
c[j] += s[i][j];
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
cout << ((r[i] + c[j]) - 2 * sum / (2 * n - 1)) / (n - 1) - s[i][j] << ' ';
}
cout << '\n';
}
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(nullptr);
cin >> t;
while (t--) {
solve();
}
return 0;
}