【 Codeforces Round #828 (Div. 3)-E1】【下取整(区间右界r/约数)*约数 凑出<r的最大的整数】【给出原数的范围,用约数凑出原数】【分解质因数】【dfs】

 这个做法任然被 hack掉了,但是有利于锻炼深搜

/*
一般如果题目中给了两种情况,
一种是easy的有可能用暴力(深搜)
像本题,我就没想到还可以把质因数一个一个存进数组去
一开始印象是觉得这样非常大,不太可行  
*/


#include <bits/stdc++.h>
#define x first
#define y second
using namespace std;
typedef long long LL;
typedef pair<LL,LL> PLL;
const int N=2e5+10;
//LL ansx=1,ansy==1;
LL a,b,c,d;
LL aa,bb;
//[a,c],[b,d] 
LL resx,resy;
LL C[N];
LL m;

bool flag;

void dfs(int idx,LL ansx,LL ansy)
{

	if(flag) return;
	if(idx==m+1) 
	{
		LL ax=(c/ansx)*ansx;
        LL ay=(d/ansy)*ansy; 
        if(ax>aa&&ay>bb)
        {
          	resx=ax;
        	resy=ay;
        	flag=true;
        	return;
    	}
    	
    	//第二种情况,ax和ay互换一下
		ax=(c/ansy)*ansy;
		ay=(d/ansx)*ansx;
		
		if(ax>aa&&ay>bb)
        {
          	resx=ax;
        	resy=ay;
        	flag=true;
        	return;
    	}
		    	
	   return;
    }
    
    
    LL p=C[idx];  //取出当下质因数
    
    
    if(ansx>c||ansy>d)
    {
    	return;
	}
    
    
	dfs(idx+1,ansx*p,ansy);
	dfs(idx+1,ansx,ansy*p); 
	
}


void solve()
{

	cin>>a>>b>>c>>d;
	aa=a;
	bb=b;
	
	unordered_map<LL,LL> mp;
	//[a,c],[b,d] 
	/*
	最终的结果是:x*y=k*a*b;
	打算先分别对a,b分解质因数 
	*/
	
	
	//<一>分解质因数的过程 
//	vector<PLL> A,B;
	for(int i=2;i*i<=a;i++)
	{
		if(a%i==0)
		{
			int cnt=0;
			while(a%i==0)
			{
				a/=i;
				cnt++;
			}
			
			//A.push_back({i,cnt});
			mp[i]+=cnt;
		}
	}
	
	if(a)
	{
		//A.push_back({a,1});
		mp[a]+=1;
	}
	
	for(int i=2;i*i<=b;i++)
	{
		if(b%i==0)
		{
			int cnt=0;
			while(b%i==0)
			{
				b/=i;
				cnt++;
			}
			
			//B.push_back({i,cnt});
			mp[i]+=cnt;
		}
	}
	if(b)
	{
		//B.push_back({b,1});
		mp[b]+=1;
	}
	
	

	
	//把两者的质因数都用mp存在一起了,现在把他们调出来 
    

	//比如一个质因子p,它有cnt 个,我们应该一个一个把它存入数组中,(为了方便dfs) 
	for(auto it:mp)
	{
		LL p=it.x,cnt=it.y;
		for(int k=1;k<=cnt;k++)
		{
			C[++m]=p;
		}
	}
	
	
	sort(C+1,C+1+m);  //对所有的质因数排个序 
	
	//现在要凑成x*y=k*a*b
	/*
	x的范围是在 [a,c]
	y的范围是在 [b,d] 
	
	我是打算用dfs凑出x和y的约数ansx,和 ansy 
	然后用c/ansx下取整 *ansx  求出 >a的最大整数    (保证该整数>a&&<=c) 
	用   d/ansy 下取整 *asny  求出 >b的最大整数   (保证该整数 >b&&<=d)
	*/  
	
    
    dfs(1,1,1);
    
    if(flag) cout<<resx<<" "<<resy<<endl;
    else cout<<"-1 -1"<<endl; 
    
    
    
	return;	
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	int T;
	cin>>T;
	while(T--)
	{
		flag=false;
		m=0;
		solve();
	}
	
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值