poj2429 GCD LCM Inverse 数论 质因数分解

2023-10-12 11:50

本文主要是介绍poj2429 GCD LCM Inverse 数论 质因数分解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题意:输入两个数分别为 c , d
找到最小的 a + b
使得 Gcd(a,b) = c ; Lcm(a,b) = d;
找到 这样 的 a 与 b ,使得 a+b最小,而且要让 a<=b.
分析:
令 gcd(a,b) = c ,lcm(a,b) = d.
分析gcd与lcm的性质,有
gcd(a,b) * lcm(a,b) = a * b;
也就是 c * d = a * b,等式两边同时除以 c.
有 (d/c) = (a/c) * (b/c);
令 C = (d/c) , x1 = (a/c) ,x2 =(b/c) ,其中 x1与x2显然是互素的,因为它们都除以了彼此的最大公约数.
现在我们的目标是 找到x1 * x2 =C 而且x1+ x2最小.
一种显然的想法是,当且仅当x1 == x2时 ,x1 +x2 最小.
也就是x1 与 x2是尽量靠近 C \sqrt{C} C
那么直接去暴力枚举它附近的约数不就好了吗.
枚举代码,其中mid就是 sqrt( C ).

for(ll fac = mid ; fac>=1;fac--){if(C % fac ==0) {ans1 = fac;break;}}for(ll fac = mid;fac <=C;fac++){if(C%fac ==0){ans2 = fac;break;}}

不幸的是,这种做法超时了,因为数字太大了,可能枚举了很长一段的数字都没有出现约数导致超时,迫使我们放弃这种思路.
回到该式子:x1 * x2 =C 其中x1,x2互素.那么是否可以直接枚举x1与x2呢?
因为x1与x2是互素的,意味着C分解出来的质因数次数要全部选取完毕
比如说 C = 2 3 ∗ 3 2 ∗ 5 4 C = 2^3 * 3 ^2 * 5^4 C=233254
可能的组合有 x 1 = 2 3 , x 2 = 3 2 ∗ 5 4 x1 = 2^3,x2=3^2*5^4 x1=23,x2=3254
x 1 = 2 3 ∗ 3 2 , x 2 = 5 4 x1=2^3*3^2,x2=5^4 x1=2332,x2=54
x 1 = 2 3 ∗ 3 2 ∗ 5 4 , x 3 = 1 x1=2^3*3^2*5^4,x3=1 x1=233254,x3=1
就是若x1中含有了某个素数因子,那么就要把它的指数全部取完,否则x2也会含有该素数因子,
使得x1与x2不满足互素的情况.
那么思路已经很显然了,对于每个素数因子,只有拿与不拿两种决策,让我们考虑下C的数据范围下最多会有多少个素数因子.
暴力地把前23个素数相乘,得到的结果大约是 1 0 29 10 ^ {29} 1029级别,早已超过了long long范围数.
而二进制枚举可以接受的复杂度是26左右,显然已经可以满足本题(n<23)的要求.
做法:
对 C进行质因数分解,算法使用Pollard - Rho.然后二进制枚举出所有的因数,找到最小的
x1 + x2. 最后结果输出 x1 * c + x2 * c.注意要让x1<x2.
最后,不要忘了对C=1的情况进行特判,因为Pollard -Rho算法不能接受C=1的情况.
Ac代码,用时47ms.

#include<iostream>
#include<cstdio>
#include<cmath>
#include<vector>
#include<algorithm>
#include<map>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn = 3e5+2;
const ll INF = 1e18;
const ll MOD = 1e18;
int prime[10]={2,3,5,7,11,13,19,61,29,37};
struct Prime{ll f_mul(ll x,ll y,ll mod){return ( x * y - (ll) ( (long double) x / mod*y )*mod + mod ) % mod;}ll f_pow(ll a,ll b,ll mod){ll ans = 1;while(b){if(b&1) ans= f_mul(ans,a,mod);b>>=1;a = f_mul(a,a,mod);}return ans%mod;
}ll gcd(ll a,ll b){if(b==0) return a;return gcd(b,a%b);}bool check(ll p,ll x){// to check  whether x is a prime.if(x % p ==0) return false;ll k = x - 1;ll t = f_pow(p%x,k,x);if(t!=1) return false;while(!(k&1)){ //一直到 k不是奇数为止 t = f_pow(p,k>>=1,x);if(t!=1&&t!=x-1) return false;if(t==x-1) return true;// t =x -1 而不是1的情况下 不能继续套用二次探索// 因为 x ^2  ≡1 是二次探索的右边 这时候右边是 x - 1 不能继续用了 认为通过测试. }return true;}bool Miller_Rabin(ll x){for(int i=0;i<10;i++){if(prime[i]==x) return true;if(!check(prime[i],x)) return false;}return true;}vector<ll> div;//储存分解之后的质因数 是无序的  需要进行处理.map<ll,int> div_cnt;//质因数的次数vector<ll> vec; ll ABS(ll x){return x>=0 ? x : (-x) ;}ll dfs(ll n){ll x1 = 0 , x2 =0, c= rand()%(n-1) + 1;ll val = 1;for(ll i=1;;i<<=2,x1=x2,val=1){for(ll j = 1;j<=i;++j){x2 = (f_mul(x2,x2,n)+c)%n;val =(f_mul(val,ABS(x1-x2),n))%n;if(j%127==0){ll d = gcd(val,n);if(d>1) return d;}}ll d = gcd(val,n);if(d>1) return d;}}void fac(ll n){if(n<2) return ;if(Miller_Rabin(n)) {div.push_back(n); return ;}ll p = n;while(p>=n) p = dfs(n);while(n%p==0) n/=p;fac(n);fac(p);}void pollard(ll n){fac(n);sort(div.begin(),div.end());div.erase(unique(div.begin(),div.end()),div.end());for(vector<ll>::iterator it=div.begin();it!=div.end();it++){while(n%(*it)==0) n/=(*it),div_cnt[(*it)]++;}for(vector<ll>::iterator it = div.begin();it!=div.end();it++){vec.push_back(f_pow((*it),div_cnt[(*it)],MOD));}}
};
int main(){ll c,d;Prime p;while(scanf("%lld %lld",&c,&d)==2){p.div.clear();p.div_cnt.clear();p.vec.clear();ll C = d / c;if(C==1){//特判  c =d的情况  cout<<c<<" "<<c<<"\n";continue;}p.pollard(C);//质因数分解vector<ll> &vec = p.vec;int n = vec.size();ll ans=INF,ans1,ans2;for(int s = 1 ;s<(1<<n);s++){ll ans_t1=1,ans_t2=1;for(int i=0;i<n;i++){if( s&(1<<i) ) ans_t1*=vec[i];    }ans_t2 = C/ans_t1;if(ans_t1+ans_t2<ans) {ans1=ans_t1,ans2=ans_t2;ans = ans_t1+ans_t2;}
}
if(ans1>ans2) swap(ans1,ans2);cout<<ans1*c<<" "<<ans2*c<<"\n";
}
return 0;}

在这里插入图片描述

这篇关于poj2429 GCD LCM Inverse 数论 质因数分解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/195635

相关文章

数论入门整理(updating)

一、gcd lcm 基础中的基础,一般用来处理计算第一步什么的,分数化简之类。 LL gcd(LL a, LL b) { return b ? gcd(b, a % b) : a; } <pre name="code" class="cpp">LL lcm(LL a, LL b){LL c = gcd(a, b);return a / c * b;} 例题:

数论ZOJ 2562

题意:给定一个数N,求小于等于N的所有数当中,约数最多的一个数,如果存在多个这样的数,输出其中最大的一个。 分析:反素数定义:对于任何正整数x,其约数的个数记做g(x).例如g(1)=1,g(6)=4.如果某个正整数x满足:对于任意i(0<i<x),都有g(i)<g(x),则称x为反素数。 性质一:一个反素数的质因子必然是从2开始连续的质数。 性质二:p=2^t1*3^t2*5^t3*7

POJ2247数论

p = 2^a*3^b*5^c*7^d 求形如上式的第n小的数。 import java.io.BufferedReader;import java.io.InputStream;import java.io.InputStreamReader;import java.io.PrintWriter;import java.math.BigInteger;import java.u

CSP-J基础之数学基础 初等数论 一篇搞懂(一)

文章目录 前言声明初等数论是什么初等数论历史1. **古代时期**2. **中世纪时期**3. **文艺复兴与近代**4. **现代时期** 整数的整除性约数什么样的整数除什么样的整数才能得到整数?条件:举例说明:一般化: 判断两个数能否被整除 因数与倍数质数与复合数使用开根号法判定质数哥德巴赫猜想最大公因数与辗转相除法计算最大公因数的常用方法:举几个例子:例子 1: 计算 12 和 18

CSP-J基础之数学基础 初等数论 一篇搞懂(二)

文章目录 前言算术基本定理简介什么是质数?举个简单例子:重要的结论:算术基本定理公式解释:举例: 算术基本定理的求法如何找出质因数:举个简单的例子: 重要的步骤:C++实现 同余举个例子:同余的性质简介1. 同余的自反性2. 同余的对称性3. 同余的传递性4. 同余的加法性质5. 同余的乘法性质 推论 总结 前言 在计算机科学和数学中,初等数论是一个重要的基础领域,涉及到整数

2014年暑假培训 - 数论

A银河上的星星 /**************************************************************     Problem: 1014     User: DoubleQ     Language: C++     Result: Accepted     Time:190 ms     Memor

ZOJ1007(数论)

题目链接:点击打开链接 解题思路:   纯粹的数学题,没有输入,直接要求输出.直接给出的求和式子极限到无穷,无法直接计算.Hint里给出了提示,大意就是说求g(x) - g(1)的求和极限,最后再加上g(1)就能求出g(x).   由g(x)  - g(1) 能够得出 1 / k*(k+x) - 1 / k * (k + 1) = (1 - x) / k * ( k + 1) * (k

每日一题~cf 970 div3 (A思维,B小模拟,C二分,D排列数建图成环,E 26个字母暴力+前缀和,F 逆元,G 数论gcd )

A 题意: 有 a 个1 ,b 个2.问是否能将这些数划分为两个数值相等的集合。 输出 YES 或者 NO —————— 问题等价于 将数组 分成两个数值相同的数组。所以sum 应该是偶数。也就是说 1 的个数是偶数。在i1的个数是偶数的情况下,将 2 分成两份,如果2 的个数是偶数,OK。如果是奇数那么需要1来补齐,如果1 的个数大于等于2那么可以补齐。(1 的个数是偶数,需要2个1来补齐,剩下

iOS——GCD再学习

GCD 使用GCD好处,具体如下: GCD 可用于多核的并行运算;GCD 会自动利用更多的 CPU 内核(比如双核、四核);GCD 会自动管理线程的生命周期(创建线程、调度任务、销毁线程);程序员只需要告诉 GCD 想要执行什么任务,不需要编写任何线程管理代码。 任务与队列 概念 **任务:就是执行操作的意思,换句话说就是你在线程中执行的那段代码。**在 GCD 中是放在 block 中

GCD常用函数拾遗

目录 dispatch_block_t监听block执行结束dispatch_block_waitdispatch_block_notify 撤销block总结参考 这几天偶尔又回顾了下GCD的知识。之前我一直以为自己对于GCD已经大体有个整体掌握了,却发现仍还有一些知识点的遗漏。于是写在这里,算是对之前GCD常用函数文章的补充。 dispatch_block_t 在GCD中