AT_abc347_d 的題解

Jerry_heng發表於2024-03-31

(一)

數學題。

根據 \(C\) 的值,可以得出 \(x\)\(y\)\(s1+s\) 個相同的數位和 \(s2\) 個不同的數位。

\(s1\)\(C\) 的二進位制中 \(0\) 的數量,\(s2\)\(C\) 的二進位制中 \(1\) 的數量。

\(x\)\(y\) 可以透過在開頭放 \(s\)\(1\) 的方式既不改變異或大小,又能湊到 \(a\)\(b\)

然後按 \(1\) 的個數列出方程,設 \(x\) 的相同數位中有 \(x'\)\(0\),不同數位中有 \(y'\)\(0\)

\[s1+s-x'+s2-y'=a \]

\[s1+s-x'+y'=b \]

解這個不定方程即可。

注意要判斷 \(x\)\(y\) 是否 \(<2^{60}\)

(二)

AC 程式碼。

#include<bits/stdc++.h>
#define int long long
using namespace std;
int a,b,c,pos[20010],n,s1,s2,s,X[20010],Y[20010],cc;
signed main(){
	cin>>a>>b>>c;
	cc=c;
	while(c>0){
		pos[++n]=c&1;
		c>>=1;
		s1+=pos[n]==0,s2+=pos[n]==1;
	}
	if((s2+b-a)%2==1){
		cout<<-1;
		return 0;
	}
	int y=(s2+b-a)/2,x;
	int p=2*s1+s2-b-a;
	if(abs(p)%2==1){
		cout<<-1;
		return 0;
	}
	if(p>0)s=0,x=p/2;
	else x=0,s=(-p)/2;
	if(n+s>60){
		cout<<-1;
		return 0;
	}
	for(int i=1;i<=n;i++){
		if(pos[i]==0){
			if(x)X[i]=0,x--;
			else X[i]=1;
			Y[i]=X[i];
		}
		else{
			if(y)X[i]=0,y--;
			else X[i]=1;
			Y[i]=X[i]^1;
		}
	}
	for(int i=1;i<=s;i++)n++,X[n]=Y[n]=1;
	int sx=0,sy=0;
	p=1;
	for(int i=1;i<=n;i++){
		sx+=X[i]*p,sy+=Y[i]*p;
		p*=2;
	}
	int ssx=sx,ssy=sy;
	while(ssx>0){
		a-=ssx&1;
		ssx>>=1;
	}
	while(ssy>0){
		b-=ssy&1;
		ssy>>=1;
	}
	if(n<=60&&a==0&&b==0&&(sx^sy)==cc)cout<<sx<<" "<<sy<<endl;
	else cout<<-1;
	return 0;
}