# 2017-2018 ACM-ICPC, NEERC, Northern Subregional Contest(Dividing Marbles-构造)

10101
10101->10000 +100 +1 //2步
10000 -> 1000 -> 100 -> .. -> 1　//n步

101…101

101…101->101…+101
101… -> … -> 101
101 -> 100 +1
100 -> … ->1

101….11
101…101->101…+11
101… -> … -> 101
101 -> 11 + 10
11 -> 10 + 1
10 -> 1

10000111 用2步除3

#include<bits/stdc++.h>

using namespace std;

const double eps=1e-10;
const double pi=3.1415926535897932384626433832795;
const double eln=2.718281828459045235360287471352;

#define LL long long
#define IN freopen("in.txt", "r", stdin)
#define OUT freopen("out.txt", "w", stdout)
#define scan(x) scanf("%d", &x)
#define mp make_pair
#define pb push_back
#define sqr(x) (x) * (x)
#define pr(x) printf("Case %d: ",x)
#define prn(x) printf("Case %d:\n",x)
#define prr(x) printf("Case #%d: ",x)
#define prrn(x) printf("Case #%d:\n",x)
#define lowbit(x) (x&(-x))
#define fi first
#define se second
typedef long long ll;
typedef pair<int,int> pii;
typedef vector<int> vi;
int a[100];
int cnt=0;
struct node{
int x,y,z;
}ans[1000];
int work(ll p) {
for(ll j=1;j<=(1<<30);j<<=1LL ) {
if (j&p) {
return j;
}
}
}

int main()
{
freopen("dividing.in","r",stdin);
freopen("dividing.out","w",stdout);
int T;scanf("%d",&T);
while(T--) {
int n=4,p=0;
for(int i=1;i<=n;i++) scanf("%d",&a[i]),p+=1<<a[i];
cnt=0;

while(p%3==0 && (int)log2(p)-(int)log2(p/3)==2 ) {
if (__builtin_popcountll(p)<__builtin_popcountll(p/3)) {
break;
}
ans[++cnt]={p,p-p/3,p/3};
ans[++cnt]={p-p/3,p/3,p/3};
p/=3;
}

vi v;
n=0;
for(ll i=0,j=1;j<=(1<<30);i++,j<<=1LL ) {
if (j&p) {
v.pb(j);
a[++n]=i;
}
}

int sz=n;
if (v.size()<=3 || (v.size()==4 && !((a[2]-a[1]==a[4]-a[3])||(a[2]-a[1]==a[4]-a[3]-1)) )) {
ll p2=v[sz-1];
if (sz>=2)
ans[++cnt]={p,v[0],p-v[0]};
if (sz>=3)
ans[++cnt]={p-v[0],p-v[0]-v[1],v[1]};
if (sz>=4)
ans[++cnt]={p-v[0]-v[1],p-v[0]-v[1]-v[2],v[2]};
while(p2>1) {
ans[++cnt]={p2,p2/2,p2/2};p2/=2;
}

}
else {
ans[++cnt]={p,v[0]+v[1],v[2]+v[3] };
int L=v[0]+v[1],R=v[2]+v[3];

for(int t=1;t<=a[3]-a[1];++t) {
ans[++cnt]={R,R/2,R/2};R/=2;
}
if (L<R) {
ans[++cnt]={R,L,R-L};
}
ans[++cnt]={L,v[0],v[1]};
int p2=v[1];
while(p2>1) {
ans[++cnt]={p2,p2/2,p2/2};p2/=2;
}
}
printf("%d\n",cnt);
for(int i=1;i<=cnt;i++)
printf("%d %d %d\n",ans[i].x,ans[i].y,ans[i].z);

}
return 0;
}

09-06 145

11-23 421

10-14 312

09-20 2671

09-30 309

04-08 549

10-26 131

03-07 55

04-03 109

10-24 193

#### 2016-2017 ACM-ICPC, NEERC, Central Subregional Contest

©️2020 CSDN 皮肤主题: 编程工作室 设计师: CSDN官方博客

1.余额是钱包充值的虚拟货币，按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载，可以购买VIP、C币套餐、付费专栏及课程。