codeforces 490D Chocolate 数论

10 篇文章 0 订阅

传送门:cf 490D

有两个矩形,现在可以对矩形作两种操作。

(1)将矩形去掉一半(某一边变为原来的一半,要求该边可以被2整除)

(2)将矩形去掉三分之一(某一边变为原来的三分之二,要求该边能被3整除)

问最少进行多少次操作可以使得两个矩形的面积相同,并分别输出操作之后的两个矩形的边长


可以发现,两种操作等价于去掉一个素因子2,或者把一个素因子3变成一个素因子2,对其他的素因子不会产生影响,因此首先把剔除2,3的素因子,判断剩余的素因子集合的乘积是否相等,若不相等则无法通过操作使得乘积相等。

然后使得记录使得素因子3和2相等

/******************************************************
 * File Name:   d.cpp
 * Author:      kojimai
 * Create Time: 2014年11月23日 星期日 18时23分21秒
******************************************************/

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
int cnt2[5];
int cnt3[5];
int main()
{
	long long x1,y1,x2,y2;
	cin>>x1>>x2;
	cin>>y1>>y2;
	long long t1 = x1,t2 = x2,k1 = y1,k2 = y2;
	memset(cnt2,0,sizeof(cnt2));
	memset(cnt3,0,sizeof(cnt3));
	while(t1 % 2==0)
	{
		t1 /= 2;
		cnt2[0]++;
	}
	while(t1 % 3==0)
	{
		t1 /= 3;
		cnt3[0]++;
	}
	while(t2 % 2==0)
	{
		t2 /= 2;
		cnt2[1]++;
	}
	while(t2 % 3==0)
	{
		t2 /= 3;
		cnt3[1]++;
	}
	while(k1 % 2==0)
	{
		k1 /= 2;
		cnt2[2]++;
	}
	while(k1 % 3==0)
	{
		k1 /= 3;
		cnt3[2]++;
	}
	while(k2 % 2==0)
	{
		k2 /= 2;
		cnt2[3]++;
	}
	while(k2 % 3==0)
	{
		k2 /= 3;
		cnt3[3]++;
	}
	//分别记录下四条边中素因子2,3的个数
	if(t1 * t2 != k1 * k2)//剩余的素因子的乘积不等
		cout<<-1<<endl;
	else
	{
		int ans = 0;
		int x3 = cnt3[0] + cnt3[1];//第一个矩形中2的个数
		int y3 = cnt3[2] + cnt3[3];//第一个矩形中3的个数
		int x4 = cnt2[0] + cnt2[1];//第二个矩形中2的个数
		int y4 = cnt2[2] + cnt2[3];//第二个矩形中3的个数
		int xd3 = 0,yd3 = 0,xd4 = 0,yd4 = 0;
		if(x3 > y3)
		{
			xd3 = x3 - y3;
			x4 += xd3;//每去掉一个素因子3就对应需要增加一个素因子2
			ans += xd3;
		}
		else if(x3 < y3)
		{
			yd3 = y3 - x3;
			y4 += yd3;
			ans += yd3;
		}
		//对素因子3操作使得3的个数相等
		if(x4 > y4)
		{
			xd4 = x4 - y4;
			ans += xd4;
		}
		else if(x4 < y4)
		{
			yd4 = y4 - x4;
			ans += yd4;
		}
		//对素因子2操作使得2的个数相等
		printf("%d\n",ans);
		if(xd3)//需要对第一个矩形进行去三分之一的操作
		{
			while(x1 % 3 == 0 && xd3)
			{
				x1 = x1 / 3 * 2;
				xd3--;
			}
			while(x2 % 3 == 0 && xd3)
			{
				x2 = x2 /3 * 2;
				xd3--;
			}
		}
		if(xd4)//需要对第一个矩形进行去二分之一的操作
		{
			while(x1 % 2 == 0 && xd4)
			{
				x1 = x1 / 2;
				xd4--;
			}
			while(x2 % 2 == 0 && xd4)
			{
				x2 /= 2;
				xd4--;
			}
		}
		if(yd3)//需要对第二个矩形进行去三分之一的操作
		{
			while(y1 % 3 == 0 && yd3)
			{
				y1 = y1/3*2;
				yd3--;
			}
			while(y2 % 3 == 0 && yd3)
			{
				y2 = y2/3*2;
				yd3--;
			}
		}
		if(yd4)//需要对第二个矩形进行去二分之一的操作
		{
			while(y1 % 2 == 0 && yd4)
			{
				y1 = y1 / 2;
				yd4--;
			}
			while(y2 % 2 == 0 && yd4)
			{
				y2 /= 2;
				yd4--;
			}
		}
		cout<<x1<<' '<<x2<<endl;
		cout<<y1<<' '<<y2<<endl;
	}
	return 0;
}

需要的操作数,并对应修改边的长度即可


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值