题目链接
http://codeforces.com/contest/1285/problem/C
题目大意
给一个数,作为两个正整数的lcm,让你最小化这两个数中最大的数,并输出。
解题思路
一开始想到的是二分,二分b枚举a,交上果断wa,好像不满足二分性质,改变思路:
对于两个数的lcm,设这两个数分别为a、b,对a,b进行质因子分解:
a = p 1 s 1 ∗ p 2 s 2 ∗ . . . ∗ p n s n a=p_1^{s_1}*p_2^{s_2}*...*p_n^{s_n} a=p1s1∗p2s2∗...∗pnsn
b = p 1 t 1 ∗ p 2 t 2 ∗ . . . ∗ p n t n b=p_1^{t_1}*p_2^{t_2}*...*p_n^{t_n} b=p1t1∗p2t2∗...∗pntn
则: l c m ( a , b ) = p 1 m a x ( s 1 , t 1 ) ∗ p 2 m a x ( s 2 , t 2 ) ∗ . . . ∗ p n m a x ( s n , t n ) lcm(a,b)=p_1^{max(s_1,t_1)}*p_2^{max(s_2,t_2)}*...*p_n^{max(s_n,t_n)} lcm(a,b)=p1max(s1,t1)∗p2max(s2,t2)∗...∗pnmax(sn,tn)
现在咱已经知道了lcm(a,b),所以可以先对其进行质因子分解,然后就知道了 p 1 , . . . p n p_1,...p_n p1,...pn以及对应的幂指数,我们要得到a和b,其实是逆过程找最小值,由于n不会太大,所以可以二进制枚举,将各项质因子的幂重新分配到a,b,取枚举中的max(a,b)最小的那组。
举个例子:
假设lcm(a,b)=24.
24 = 2 3 ∗ 3 1 24=2^3*3^1 24=23∗31
二进制枚举到(1<<2)-1,也就是1-3
1: 01 则 a = 2 0 ∗ 3 1 , b = 2 3 ∗ 3 0 a=2^0*3^1,b=2^3*3^0 a=20∗31,b=23∗30 所以: a = 3 , b = 4 a=3,b=4 a=3,b=4
2: 10 则 a = 2 3 ∗ 3 0 , b = 2 0 ∗ 3 1 a=2^3*3^0,b=2^0*3^1 a=23∗30,b=20∗31 所以: a = 4 , b = 3 a=4,b=3 a=4,b=3
3: 11 则 a = 2 3 ∗ 3 1 , b = 2 0 ∗ 3 0 a=2^3*3^1,b=2^0*3^0 a=23∗31,b=20∗30 所以: a = 24 , b = 1 a=24,b=1 a=24,b=1
显然前两种max(a,b)最小,所以答案为(3,4).
参考代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef pair<ll,int> P;
const ll inf=1e12+7;
const int maxn=1e5+7;
#define ft first
#define sd second
#define pb push_back
int t;
ll x;
int len=0;
vector<P> v;
vector<int> s;
void getp(ll xx){//质因子分解
for(ll i=2;i*i<=xx;i++){//昨晚这里忘记开long long,一直TLE,快哭了
v.pb(P(i,0));
while(xx%i==0)xx/=i,++v.back().sd;
if(!v.back().sd)v.pop_back();
}
if(xx>1)v.pb(P(xx,1));
}
ll qpow(ll a,ll n){
ll ret=1;
while(n){
if(n&1)ret*=a;
a*=a;
n>>=1;
}
return ret;
}
void solve(int xx,ll &l,ll &r){//二进制枚举
s.clear();
ll a=1,b=1;
while(xx){
s.pb(xx%2);
xx/=2;
}
int lwl=s.size();
for(int i=lwl+1;i<=len;i++)s.pb(0);
for(int i=0;i<len;i++){
if(a>=r||b>=r)return;
if(s[i]==1){
if(v[i].sd==1)a*=v[i].ft;
else a*=qpow(v[i].ft,v[i].sd);
}
else {
if(v[i].sd==1)b*=v[i].ft;
else b*=qpow(v[i].ft,v[i].sd);
}
}
if(a>b)swap(a,b);
if(b<r){
r=b,l=a;
}
}
int main()
{
cin>>x;
v.clear();
ll no=x;
getp(no);
len=(int)v.size();
if(len==1||len==0){
printf("1 %lld\n",x);return 0;
}
ll l=1,r=x;
ll n=1<<len;
for(int i=1;i<n;i++){
solve(i,l,r);
}
if(l>r)swap(l,r);
cout<<l<<' '<<r<<'\n';
return 0;
}