牛客训练赛4 A - Sixteen 题解
A - Sixteen 题解
这题好难。。。
问题重述
给定整数 \(x\)(\(|x|<2^{75}\)),构造不超过 \(16\times16\) 的整数矩阵 \(A\),满足:
- 所有元素 \(A_{i,j}\in[-16,16]\);
- \(\det(A)=x\)。
核心思路
固定 \(n=16\),前 \(15\) 列固定,仅最后一列为变量 \((a_1,\dots,a_{16})^{\mathsf T}\)。由行列式对列线性:
其中系数向量 \((c_1,\dots,c_{16})\) 是前 \(15\) 列的左零空间向量,即对任意 \(j\in[1,15]\):
问题转化为:设计前 \(15\) 列以产生合适的权值 \(c_i\),再用 \(a_i\in[-16,16]\) 凑出目标 \(x\)。
矩阵构造
前 \(15\) 列固定为:
即:
行变换
从下到上做 \(R_i\leftarrow R_i-R_{i-1}\)(\(i=16,\dots,2\)),行列式不变。
前 15 列变化
考察 \(R_i-R_{i-1}\)(\(i\ge2\))的前 \(15\) 列:
| 列 \(j\) | \(R_i\) 原值 | \(R_{i-1}\) 原值 | 差值 |
|---|---|---|---|
| \(j<i-1\) | \(16\) | \(16\) | \(0\) |
| \(j=i-1\) | \(16\) | \(15\) | \(1\) |
| \(j=i\) | \(15\) | \(-16\) | \(31\) |
| \(j=i+1\) | \(-16\) | \(0\) | \(-16\) |
| \(j>i+1\) | \(0\) | \(0\) | \(0\) |
变换后前 \(15\) 列为三对角结构(\(R_1\) 不变,\(R_{15}\) 无 \(-16\) 列):
最后一列变化
将变换后的矩阵记为 \(B\),\(\det B=\det A\)。
Laplace 展开与递推序列
沿第 16 列展开
其中 \(M_i\) 是删去第 \(i\) 行和第 \(16\) 列后的 \(15\times15\) 余子式。\(i+16\) 为偶数时 \((-1)^{i+16}=(-1)^i\),故:
定义 \(D_k\)
设 \(T\) 为变换后前 \(15\) 列构成的 \(16\times15\) 矩阵。定义 \(D_k\) 为 \(T\) 左上角 \(k\times k\) 主子式的行列式:
验证:
对 \(D_k\) 沿最后一列展开,得递推:
证明 \(M_i=D_{i-1}\)
\(M_i\) 删去第 \(i\) 行和第 \(16\) 列后,剩余的 \(15\times15\) 矩阵分上下两块:
- 上块(第 \(1\sim i-1\) 行):前 \(i-1\) 列恰为 \(T\) 左上角 \((i-1)\times(i-1)\) 主子式,行列式 \(D_{i-1}\)。
- 下块(第 \(i+1\sim16\) 行):从第 \(i\) 列起为:
下块是上三角矩阵,对角元全为 \(1\),行列式为 \(1\)。利用分块行列式性质可得 \(M_i=D_{i-1}\cdot1=D_{i-1}\)。
最终展开式
代入 \(M_i=D_{i-1}\):
换元
令 \(a_i=(-1)^i u_i\),\(u_i\in[-16,16]\)。则:
代入整理:
提取公因子 16
归纳可证 \(D_k\equiv(-1)^k\pmod{16}\),故 \(D_{i-1}+D_i\equiv0\pmod{16}\)。
定义:
则:
第一步:处理模 16
为什么必做这一步
令 \(\det(A)=x\),由前述公式:
右边是 \(16\times\)整数,故左边 \(x-D_{15}u_{16}\) 必须被 \(16\) 整除。这不是附加要求,而是等式结构本身的约束。
用 \(u_{16}\) 吸收模 \(16\) 余数
\(D_{15}\equiv-1\pmod{16}\),所以条件等价于:
为何 \(u_{16}\in[-8,7]\)
区间 \([-8,7]\) 恰好包含 \(16\) 个整数,构成模 \(16\) 的一个完全剩余系,且每个数绝对值最小:
| \(u_{16}\) | \(-8\) | \(-7\) | \(-6\) | \(-5\) | \(-4\) | \(-3\) | \(-2\) | \(-1\) | \(0\) | \(1\) | \(2\) | \(3\) | \(4\) | \(5\) | \(6\) | \(7\) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| \(\bmod16\) | \(8\) | \(9\) | \(10\) | \(11\) | \(12\) | \(13\) | \(14\) | \(15\) | \(0\) | \(1\) | \(2\) | \(3\) | \(4\) | \(5\) | \(6\) | \(7\) |
因此 \(u_{16}\equiv-x\pmod{16}\) 在 \([-8,7]\) 中有且仅有一个解,唯一性得到保证。
同时 \(D_{15}\) 的量级约为 \(10^{22}\),若 \(|u_{16}|\) 太大,\(Q\) 会额外膨胀并可能超出表示范围。选绝对值最小的代表元,最小化 \(|Q|\),确保后续贪心可行。
归结为纯权值表示
问题转化为:找 \(u_1,\dots,u_{15}\in[-16,16]\) 使:
权值序列
前缀和:
区间覆盖引理
使用权值 \(E_0,\dots,E_k\),每位系数 \(\in[-16,16]\),可表示区间 \([-16S_k,\,16S_k]\) 中所有整数。
证明(归纳):
-
\(k=0\):\(E_0=1\),系数 \([-16,16]\),显然覆盖 \([-16,16]=[-16S_0,16S_0]\)。
-
归纳:假设 \(E_0,\dots,E_{k-1}\) 覆盖 \([-16S_{k-1},16S_{k-1}]\)。加入 \(E_k\),取系数 \(d\in[-16,16]\) 时覆盖区间:
\[[dE_k-16S_{k-1},\;dE_k+16S_{k-1}] \]相邻 \(d\) 和 \(d+1\) 的区间:
\[(d+1)E_k-16S_{k-1}-(dE_k+16S_{k-1})=E_k-32S_{k-1} \]由递推可证 \(E_k\le32S_{k-1}+1\),故 \(E_k-32S_{k-1}\le1\),相邻区间无缝隙,整体连续覆盖 \([-16S_k,16S_k]\)。\(\square\)
可行性验证
计算得 \(16S_{14}=15453918795058662406416\)。
由 \(|x|<2^{75}\) 和 \(|u_{16}|\le8\) 可证:
故 \(Q\) 一定可被表示。
第二步:贪心构造 \(u_1\sim u_{15}\)
初始值
\(Q\) 的初始值即为第一步算出的:
贪心流程
从最大权值 \(E_{14}\) 开始,倒序至 \(E_0\)(\(k=14,13,\dots,0\)):
- 枚举 \(d\in[-16,16]\),找到满足 \(|Q-dE_k|\le16S_{k-1}\) 的 \(d\);
- 令 \(u_{k+1}=d\);
- 更新 \(Q\leftarrow Q-dE_k\)(剩余量缩小)。
直观理解
每一步从 \(Q\) 中扣除 \(d\cdot E_k\),将表示范围从 \([-16S_k,16S_k]\) 收缩到 \([-16S_{k-1},16S_{k-1}]\)。\(Q\) 始终保持在下标 \(k\) 对应的可达区间内,最终归零。
区间覆盖引理保证每一步必存在合法 \(d\)。
第三步:回填矩阵
令 \(a_i=(-1)^i u_i\),填入第 \(16\) 列。前 \(15\) 列按模板填入。
输出 \(n=16\) 及完整矩阵。
复杂度
每条用例枚举 \(15\times33\) 个候选值,常数时间。总复杂度 \(O(T)\)。
参考实现
#include<bits/stdc++.h>
using namespace std;
using i128=__int128;
constexpr int N=16;
i128 D[N+1],E[N],S[N];
i128 read(){
string s;
cin>>s;
i128 x=0;
int f=1,i=0;
if(s[0]=='-') f=-1,i=1;
for(;i<(int)s.size();++i) x=x*10+(s[i]-'0');
return f*x;
}
void init(){
D[0]=1,D[1]=15;
for(int i=2;i<=N;++i) D[i]=31*D[i-1]+16*D[i-2];
for(int i=0;i<N;++i) E[i]=(D[i]+D[i+1])/16;
S[0]=E[0];
for(int i=1;i<N;++i) S[i]=S[i-1]+E[i];
}
i128 ABS(i128 x){
if(x>=0) return x;
else return -x;
}
void sol(i128 x){
int u16=((-x)%16+16)%16;
if(u16>7) u16-=16;
i128 Q((x-D[15]*u16)/16);
vector<int> u(N);
u[15]=u16;
for(int k=14;k>=0;--k){
for(int d=-16;d<=16;++d){
i128 rem=ABS(Q-d*E[k]);
i128 bound((!k?0:16*S[k-1]));
if(rem<=bound){
u[k]=d;
Q=Q-d*E[k];
break;
}
}
}
cout<<N<<'\n';
for(int i=0;i<N;++i){
for(int j=0;j<N;++j){
int val;
if(j<N-1){
if(i==j) val=15;
else if(i+1==j) val=-16;
else if(i>j) val=16;
else val=0;
}else val=(i&1?1:-1)*u[i];
cout<<val<<' ';
}
cout<<'\n';
}
}
int main(){
init();
int T(1);
cin>>T;
while(T--) sol(read());
}

浙公网安备 33010602011771号