cf 1444A - Division看了老哥的博客的心得

https://blog.csdn.net/fxt275307894a/article/details/109449321?utm_medium=distribute.pc_relevant.none-task-blog-title-2&spm=1001.2101.3001.4242

这个是老哥的题解,搜了好多,就老哥这个看懂了。
改写了一点点,希望老哥不要介意

题意:输入n,再输入n对x,y。对于每一对x,y,找到一个数m,使得x%m==0 && m%y!=0 ;并且m要最大

改写是进行了分类
1.x<y, x 本身满足
2.x==y, x除以x的最小质因数,使得x2<y并且最大(x2=x/x的最小质因数)
3.x>y

  1. x%y!=0,即x不是y的倍数,x本身满足
    2)x%y==0
    在这里插入图片描述就是
    假如b里面有p个ai,a里面有k个ai,因为a是b的因数,所以k>=p,只要让a2里面只剩p-1个ai,则必有a2%b!=0
    此时a2=a/(ai ^ ( ww ) )
    p-1=k-ww
    (去掉ww个ai)
#include<cstdio>
#include<cmath>
#include<map>
#define min(a,b) ((a)<(b)?(a):(b))
using namespace std;
int n,m,k,z,f[100039],s[100039],d[100039],head,dh,t,sh;
map<long long,int> q;
long long x,y,now,tot,pus,ans,flag;
int main(){
//	freopen("1.in","r",stdin);
	register int i,j;
	for(i=2; i*i<=1e9; i++) {
		if(!f[i]) s[++head]=i;//s[i]为质数
		for(j=1; j<=head&&i*s[j]<=100000; j++) {
			f[i*s[j]]=1;
			if(i%s[j]==0) break;
		}
	}


	scanf("%d",&t);
	while(t--){
		scanf("%lld%lld",&x,&y);now=y;

        if(x<y||x%y)
        {
            printf("%lld\n",x);
            continue;
        }
        if(x==y){

               for(i=1;s[i]<=x&&i<=head;i++)
                   if(x%s[i]==0){
                    x/=s[i];
                    break;

                   }


            printf("%lld\n",x);
            continue;



        }

		dh=0;pus=1e18;
		for(i=1;s[i]*s[i]<=y&&i<=head;i++){
			if(now%s[i]==0){
				d[++dh]=s[i];//y的质因数列表
				while(now%s[i]==0)q[s[i]]++,now/=s[i];
			}
		}
		if(now!=1)q[now]++,d[++dh]=now;//最后一个质因数大于根号y的情况
		//大于根号y的因数只可能有一个
		//小于等于根号y的数从now中剔除完之后就只剩大于根号y的因数或者一
		//这里是一个优化,要找到那个质因数在for循环里可能还需要需要许多步骤,而这里只要一步
		now=x;
		for(i=1;i<=dh;i++){
			if(x%d[i]==0){//从y的质数列表来考虑
				ans=0;
				while(x%d[i]==0) x/=d[i],ans++;

					tot=1;
					for(j=1;j<=ans-q[d[i]]+1;j++) tot*=d[i];
					pus=min(pus,tot);

			}
		}

        printf("%lld\n",now/pus);//
		q.clear();
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值