• CF 1445C


    题目传送门

    题目大意是,给定(p_i)(q_i),找到一个最大的(x_i)使得(p_i mod x_i=0)(x_i mod q_i eq 0)

    分情况讨论:

    1.(p_i < q_i)时,答案为(p_i).

    2.(p_i mod q_i eq 0)时,答案为(p_i).

    3.利用唯一分解定理分解(p_i)(q_i):

    (p_i = k_1^{t_1} * k_2^{t_2} * k_3^{t_3} * ... * k_n^{t_n})

    (p_i = k_1^{r_1} * k_2^{r_2} * k_3^{r_3} * ... * k_n^{r_n})

    其中,(forall r_i,t_i)都满足(t_i geq r_i)

    而要找的(x),满足(x = k_1^{d_1} * k_2^{d_2} * k_3^{d_3} * ... * k_n^{d_n})(exists i) 使得(d_i < t_i)(d_i geq 0).

    所以最终要做的就是枚举(q_i)的所有质因子,使其次数减一,其它所有质因子次数与(p_i)里的一样(包括(q_i)不含的质因子).

    注意:对于第三种情况,(q_i)可能是一个大质数,导致我们无法枚举到那个质因子,所以答案为(p_i)除去所有(p_i)后的余数.

    下面给两份代码(一份Wa,一份AC),WA的原因是运用错误处理方法,使得对于一些因数为大质数的数分解错误.

    //AC
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    
    using namespace std;
    
    long long t,tot,zs;
    long long num[1000001],sum[1000001];
    long long x,y,ans,mx;
    bool vis[1000001];
    
    inline void oula() {
    	vis[1] = 1;
    	for(long long i = 2;i <= 1000000; i++) {
    		if(!vis[i]) num[++tot] = i;
    		for(long long j = 1;j <= tot; j++) {
    			if(num[j] * i > 1000000) break;
    			vis[num[j]*i] = 1;
    			if(i % num[j] == 0) break;
    		}
    	}
    }
    
    inline void fenjie(long long a) {
    	for(long long i = tot;i >= 1; i--) {
    		while(a % num[i] == 0) {
    			sum[i]++;
    			a = a / num[i];
    		}
    	}
    }
    
    int main() {
    	scanf("%lld",&t);
    	oula();
    	while(t--) {
    		memset(sum,0,sizeof(sum));
    		ans = 1;
    		scanf("%lld%lld",&x,&y);
    		if(x < y) {
    			printf("%lld
    ",x);
    			continue;
    		}
    		if(x % y != 0) {
    			printf("%lld
    ",x);
    			continue;
    		}
    		fenjie(y);
    		for(long long i = tot;i >= 1; i--) {
    			if(sum[i] == 0) continue;
    			long long uu = x,vv = y,m1 = 0,m2 = 0;
    			while(uu % num[i] == 0) uu /= num[i],m1++;
    			while(vv % num[i] == 0) vv /= num[i],m2++;
    			for(int j = 1;j <= m2 - 1; j++) uu *= num[i];
    			ans = max(ans,uu);
    		}
    		if(ans == 1) {
    			while(x % y == 0) x /= y;
    			ans = x;
    		}
    		printf("%lld
    ",ans);
    	}
    	return 0;
    } 
    
    //WA
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    
    using namespace std;
    
    long long t,tot,zs;
    long long num[1000001],sum[1000001];
    long long x,y,ans,mx;
    bool vis[1000001];
    
    inline void oula() {
    	vis[1] = 1;
    	for(long long i = 2;i <= 1000000; i++) {
    		if(!vis[i]) num[++tot] = i;
    		for(long long j = 1;j <= tot; j++) {
    			if(num[j] * i > 1000000) break;
    			vis[num[j]*i] = 1;
    			if(i % num[j] == 0) break;
    		}
    	}
    }
    
    inline void fenjie(long long a) {
    	for(long long i = tot;i >= 1; i--) {
    		while(a % num[i] == 0) {
    			zs++;
    			sum[i]++;
    			a = a / num[i];
    		}
    	}
    }
    
    int main() {
    	scanf("%lld",&t);
    	oula();
    	while(t--) {
    		zs = 0;
    		memset(sum,0,sizeof(sum));
    		ans = 1;
    		scanf("%lld%lld",&x,&y);
    		if(x < y) {
    			printf("%lld
    ",x);
    			continue;
    		}
    		if(x % y != 0) {
    			printf("%lld
    ",x);
    			continue;
    		}
    		fenjie(y);
    		for(long long i = tot;i >= 1; i--) {
    			if(sum[i] == 0) continue;
    			long long uu = y / num[i];
    			long long vv = x / y;
    			while(vv % num[i] == 0) vv = vv / num[i];
    			ans = max(ans,vv * uu);
    		}
    		if(zs <= 1) {
    			while(x % y == 0) x /= y;
    			ans = x;
    		}
    		printf("%lld
    ",ans);
    	}
    	return 0;
    } 
    
  • 相关阅读:
    1.python全栈之路:python基础
    21、指定元素置后——数组
    20、泰勒展开式
    19、显示表达式的运算形式
    1、模拟蚂蚁借呗—利息计算
    05、C语言——循环结构
    04、C语言——选择结构
    03、C语言——顺序结构
    02、C语言——C语言组成与数据
    07、C语言——函数
  • 原文地址:https://www.cnblogs.com/lipeiyi520/p/13922466.html
Copyright © 2020-2023  润新知