C. Number 题解——2026牛客暑期多校训练营5

C. Number 题解

构造三个长为 \(B\)\(B\) 进制数 \(P,Q,R\),要求满足 \(P,Q,R\) 的每一位数字构成 \(0\sim B-1\) 的排列,且 \([P]_B+[Q]_B=R_{B}\)

\(B\leq 10^6\)

很久没做这么古典的构造题了,也没做出来而且焦头烂额了。官方题解的思考高度很高但是看了几遍才看懂,这里简单给未来的自己陈述一下。详细思路还是建议看官方题解和讲解视频。

奇数无解

关于这个结论,我的证明如下(非官方):

考虑 \(P,Q,R\)\(B-1\) 取模的结果,以 \(P=(p_0,p_1,\dots,p_{B-1})\) 为例。

\[\begin{align} P&\equiv \sum_{i=0}^{B-1} p_iB^i\pmod{B-1}\\ &\equiv \sum_{i=0}^{B-1} p_i[B\bmod{(B-1)}]^i \pmod{B-1}\\ &\equiv \sum_{i=0}^{B-1} p_i \pmod{B-1}\\ &\equiv \frac{B(B-1)}{2}\pmod{B-1} \end{align} \]

\(B\) 为奇数时,取值为 \(\frac{B-1}{2}\)\(P+Q\neq R\)。无解

\(B\) 为偶数时,取值为 \(0\)\(P+Q=R\),满足有解的必要条件。

进位位置数为 \(\frac{B}{2}\)

然而这个证明并未带来更多结论,题解是这样证明的

设五元组 \((p_i,q_i,r_i,c_i,d_i)\),表示第 \(i\) 位上 \(P,Q,R\) 上的数字位 \(p_i,q_i,r_i\),由 \(i-1\) 位对这位有 \(c_i=0/1\) 的进位值,对 \(i+1\) 位产生了 \(d_i=0/1\) 的进位值。

同时对每个五元组内部,有

\[p_i+q_i+c_i=r_i+Bd_i \]

\(c_0=0,d_{B-1}=0,c_i=d_{i-1}\)。同时设 \(C=\sum c_i=\sum d_i\)\(S=\sum p_i=\sum q_i=\sum r_i\)

\(B\) 个二元组累加,有

\[S+S+C=S+BC\implies C=\frac{B}{2} \]

\(B\) 为奇数时是无解的,同时也说明了设内部进位总数 \(C=\frac{B}{2}\)

思路

假设我们得到了合法答案的所有五元组 \((p_i,q_i,r_i,c_i,d_i)\),但是它们现在的顺序是乱的,如何找到答案?

设当前需要考虑的进位状态为 \(x=0/1\),第 \(0\) 位需要考虑的进位 \(c_0=0\),则初始的进位状态为 \(0\)

这是一个两个点的图,每有一个五元组,考虑连一条 \(c_i\to d_i\) 的有向边,在这个图上 \(0\) 的点开始求一条欧拉回路,一定能回到 \(0\) 这个状态且经过 \(B\) 条边,欧拉回路上边的顺序就是五元组的顺序,即答案从低位到高位的顺序。

具体构造

我也不知道怎么来的,但是你玩一下就会发现有了上面的思路就非常合理。

直接 \(p_i=i,q_i=(i-2)\bmod B\),那么

\[r_i+Bd_i=p_i+q_i+c_i=2i-2+c_i\\ r_i=(2i-2+c_i)\bmod B,d_i=\lfloor(2i-2+c_i)/B \rfloor \]

可以发现 \(2i-2\bmod B\) 这个东西只能覆盖所有模 \(B\) 下为偶数的数,且每个数两次,一旦一半的 \(c_i\)\(1\),则恰好可以奇数偶数各覆盖一次。

只需要 \(c_{0\sim \frac{B}{2}-1}=1\)\(c_{\frac{B}{2}\sim B-1}=0\) 即可以满足 \(r_i\) 是完整排列,但是这样会在 \(i=1\)\(p_i=r_i\),将 \(c_1\)\(c_1,c_{\frac{B}{2}+1}\) 互换值即可。

同时你会发现恰好进位 \(d_i\) 也在一半的位置为 \(1\),这个已经由 \(p_i+q_i\) 满足。

具体实现见代码

const int N=1000006;
const ll INF=0x3f3f3f3f3f3f3f3f;
int n,idx[N],p[N],q[N],r[N],a[N],d[N];
int main(){
	scanf("%d",&n);
	if(n==4){
		puts("0 1 2 3");
		puts("1 3 0 2");
		puts("2 0 3 1");
		return 0;
	}
	if(n%2==1||n==2)return puts("-1"),0;
	for(int i=0;i<n;++i){
		p[i]=i;
		q[i]=(i-2+n)%n;
		a[i]=(i<n/2?1:0);
	}
	for(int i=0;i<n;++i){
		int x=p[i]+q[i]+a[i];
		r[i]=x%n;
		d[i]=x/n;
	}
	int tot=0;
	for(int i=0;i<n/2-2;++i){
		idx[tot++]=n/2+1+i;
		idx[tot++]=2+i;
	}
	idx[tot++]=n-1;idx[tot++]=1;
	idx[tot++]=0;idx[tot++]=n/2;
	// for(int i=n-1;i>=0;--i){
	// 	printf("%d ",idx[i]);
	// }puts("");
	for(int i=n-1;i>=0;--i){
		printf("%d ",p[idx[i]]);
	}puts("");
	for(int i=n-1;i>=0;--i){
		printf("%d ",q[idx[i]]);
	}puts("");
	for(int i=n-1;i>=0;--i){
		printf("%d ",r[idx[i]]);
	}puts("");
	return 0;
}
/*
 9 8 7 6 5 4 3 2 1 0
 7 6 5 4 3 2 1 0 9 8
 0 0 0 1 0 1 1 1 0 1
16141211 8 7 5 310 9
 6 4 2 1 8 7 5 3 0 9
 1 1 1 1 0 0 0 0 1 0

 9 8 7 6 5 4 3 2 1 0
 7 6 5 4 3 2 1 0 9 8
 0 0 0 0 0 1 1 1 1 1
16141210 8 7 5 311 9
 6 4 2 0 8 7 5 3 1 9
 1 1 1 1 0 0 0 0 1 0
*/
posted @ 2026-09-15 20:47  BigSmall_En  阅读(6)  评论(0)    收藏  举报