Codeforces 490D. Chocolate(分解质因数求解)

D. Chocolate
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

Polycarpus likes giving presents to Paraskevi. He has bought two chocolate bars, each of them has the shape of a segmented rectangle. The first bar is a1 × b1 segments large and the second one is a2 × b2 segments large.

Polycarpus wants to give Paraskevi one of the bars at the lunch break and eat the other one himself. Besides, he wants to show that Polycarpus's mind and Paraskevi's beauty are equally matched, so the two bars must have the same number of squares.

To make the bars have the same number of squares, Polycarpus eats a little piece of chocolate each minute. Each minute he does the following:

  • he either breaks one bar exactly in half (vertically or horizontally) and eats exactly a half of the bar,
  • or he chips of exactly one third of a bar (vertically or horizontally) and eats exactly a third of the bar.

In the first case he is left with a half, of the bar and in the second case he is left with two thirds of the bar.

Both variants aren't always possible, and sometimes Polycarpus cannot chip off a half nor a third. For example, if the bar is 16 × 23, then Polycarpus can chip off a half, but not a third. If the bar is 20 × 18, then Polycarpus can chip off both a half and a third. If the bar is 5 × 7, then Polycarpus cannot chip off a half nor a third.

What is the minimum number of minutes Polycarpus needs to make two bars consist of the same number of squares? Find not only the required minimum number of minutes, but also the possible sizes of the bars after the process.

Input

The first line of the input contains integers a1, b1 (1 ≤ a1, b1 ≤ 109) — the initial sizes of the first chocolate bar. The second line of the input contains integers a2, b2 (1 ≤ a2, b2 ≤ 109) — the initial sizes of the second bar.

You can use the data of type int64 (in Pascal), long long (in С++), long (in Java) to process large integers (exceeding 231 - 1).

Output

In the first line print m — the sought minimum number of minutes. In the second and third line print the possible sizes of the bars after they are leveled in m minutes. Print the sizes using the format identical to the input format. Print the sizes (the numbers in the printed pairs) in any order. The second line must correspond to the first bar and the third line must correspond to the second bar. If there are multiple solutions, print any of them.

If there is no solution, print a single line with integer -1.

Sample test(s)
input
2 6
2 3
output
1
1 6
2 3
input
36 5
10 16
output
3
16 5
5 16
input
3 5
2 1
output
-1

比赛时候爆搜做的,结果FST了,超时。当时感爆搜是因为认定这个数不断乘1/2或2/3得到的数的集合,不会超过log个,但后来想了下,个数实际上不是log级别。

正解是分解质因数。

设4个整形a1,b1,a2,b2,每次都可以对4个整形(记为x)进行两种操作,将整形x乘上1/2,或乘上2/3,要求乘上之后必须还是整形。

问,最少需要多少步,使得操作之后使得 a1*b1=a2*b2 ?

我们将a=a1*b1 , b=a2*b2;每个整数都可以质因数分解,我们进行如下质因数分解:

a=k1*(2^h1)*(3^h2);

b=k2*(2^h3)*(3^h4);

换句话说,现在要把k1*(2^h1)*(3^h2)和k2*(2^h3)*(3^h4)变成两个一样的数。

分解质因数后,可以保证gcd(k1,k2)==1,即k1和k2互质,他们与2,3 “无关”。所以,如果k1 != k2,那么就无解,输出-1,因为此时无论怎么操作,a都不会等于b

如果k1==k2,

假设h2>h4 (h2<h4情况类似,h2==h4就不需要进行这一步)

则将a乘上 (h2-h4) 个 2/3,那么此时h2就等于h4,但h1要加上(h2-h4),即h1+=h2-h4;

然后再比较h1和h3

假设h1>h3 (h1<h3情况类似,h1==h3就不需要进行这一步)

那么,将a乘上 (h1-h3) 个 1/2

这样一来,a就等于b了,并且答案=(h2-h4)+(h1-h3);


上述只是假设h2>h4 并且 h1+=h2-h4之后 h1>h3的情况,其他情况类似。适当分情况讨论即可

有一个小问题,这只是解得最小的操作步骤,但a1 b1 a2 b2操作后的结果是多少呢?适当记录下来,更新维护即可了,就不说了。


代码如下:

//Hello. I'm Peter.
#include<cstdio>
#include<iostream>
#include<sstream>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<cctype>
#include<ctime>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef long double ld;
#define peter cout<<"i am peter"<<endl
#define input freopen("data.txt","r",stdin)
#define randin srand((unsigned int)time(NULL))
#define INT (0x3f3f3f3f)*2
#define LL (0x3f3f3f3f3f3f3f3f)*2
#define gsize(a) (int)a.size()
#define len(a) (int)strlen(a)
#define slen(s) (int)s.length()
#define pb(a) push_back(a)
#define clr(a) memset(a,0,sizeof(a))
#define clr_minus1(a) memset(a,-1,sizeof(a))
#define clr_INT(a) memset(a,INT,sizeof(a))
#define clr_true(a) memset(a,true,sizeof(a))
#define clr_false(a) memset(a,false,sizeof(a))
#define clr_queue(q) while(!q.empty()) q.pop()
#define clr_stack(s) while(!s.empty()) s.pop()
#define rep(i, a, b) for (int i = a; i < b; i++)
#define dep(i, a, b) for (int i = a; i > b; i--)
#define repin(i, a, b) for (int i = a; i <= b; i++)
#define depin(i, a, b) for (int i = a; i >= b; i--)
#define pi 3.1415926535898
#define eps 1e-6
#define MOD 1000000007
#define MAXN 100100
#define N
#define M
struct Digit{
    ll k,h1,h2;
    ll m12,m23;
}da,db;
ll a1,b1,a2,b2,ans;
void Putintov(ll x,Digit &d){
    while(1){
        if(x%2==0){
            d.h1+=1;
            x/=2;
        }
        else break;
    }
    while(1){
        if(x%3==0){
            d.h2+=1;
            x/=3;
        }
        else break;
    }
    d.k*=x;
}
void caculate(Digit &d,ll &a,ll &b){
    while(d.m23){
        if(a%3LL==0){
            a=(a/3)*2;
            d.m23-=1;
        }
        else break;
    }
    while(d.m23){
        if(b%3LL==0){
            b=(b/3)*2;
            d.m23-=1;
        }
        else break;
    }
    while(d.m12){
        if(a%2LL==0){
            a/=2;
            d.m12-=1;
        }
        else break;
    }
    while(d.m12){
        if(b%2LL==0){
            b/=2;
            d.m12-=1;
        }
        else break;
    }
}
int main()
{
    cin>>a1>>b1;
    cin>>a2>>b2;
    da.k=1,da.h1=0,da.h2=0;
    da.m12=da.m23=0;
    Putintov(a1,da);
    Putintov(b1,da);
    db.k=1,db.h1=0,db.h2=0;
    db.m12=db.m23=0;
    Putintov(a2,db);
    Putintov(b2,db);
    ans=0;
    if(da.k!=db.k){
        printf("%d\n",-1);
        exit(0);
    }
    //for 3:
    if(da.h2<db.h2){
        ll d3=db.h2-da.h2;
        ans+=d3,db.m23+=d3;
        db.h1+=d3;
    }
    else if(da.h2>db.h2){
        ll d3=da.h2-db.h2;
        ans+=d3,da.m23+=d3;
        da.h1+=d3;
    }
    //for 2
    if(da.h1>db.h1){
        ll d2=da.h1-db.h1;
        ans+=d2,da.m12+=d2;
    }
    else if(da.h1<db.h1){
        ll d2=db.h1-da.h1;
        ans+=d2,db.m12+=d2;
    }
    caculate(da,a1,b1);
    caculate(db,a2,b2);
    printf("%lld\n",ans);
    printf("%lld %lld\n",a1,b1);
    printf("%lld %lld\n",a2,b2);
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值