题解 CF1285C 【Fadi and LCM】
这道题是2020年1月10日CF比赛的C题(不用讲也都知道)
题目大意:
给你一个整数x,找出一对满足:
- 最小公约数为x
- 两个数中最大的数最小
(本人语文及其不好,看不懂还是看翻译吧!)
本人的想法
似乎许多大佬都是根号级算法。我在看题目的时候,最先想到的是暴力质因数分解
根据唯一定理 ,x=p1^a1 p2^a2 ...... * pk^ak
(我不会LaTeX,就将就一下吧)
那我们就将这k个数(将pi^ai看做一个数),分成两份,让分出来最大的数最小,就行了(若将pi^ai分成pi^(ai-k)和pi^k,最小公约数一定不是x,而两个数都选择x的因子,互质,就能满足最小)
代码实现
由于这是暴力+质因数分解,代码很好理解的
#include<cmath>
#include<stdio.h>
#include<cstring>
#include<iostream>
#include<algorithm>
//#define int long long
using namespace std;
const int MAXN=1005;
const int MAXM=1000005;
bool v[MAXM];
int n,m,tot,ans1,ans2,a[MAXN],prime[MAXM];
inline int Max(int a,int b){return a<b?b:a;}
inline void primes(){
memset(v,1,sizeof v);
v[0]=v[1]=0;
for(int i=2;i<=MAXM;i++){
if(v[i]) prime[++m]=i;
for(int j=1;j<=m;j++){
if(i*prime[j]>MAXM) break;
v[i*prime[j]]=0;
if(i%prime[j]==0) break;
}
}
return;
}
inline int Quickpow(int a,int b){
int ans=1;
while(b){
if(b&1) ans=ans*a;
b/=2;a*=a;
}
return ans;
}
inline void work(int x){
for(register int i=1;i<=m&&prime[i]*prime[i]<=x;++i)
if(x%prime[i]==0){
int sum=0;
while(x%prime[i]==0){
sum++;
x/=prime[i];
}
a[++tot]=Quickpow(prime[i],sum);
}
if(x>1) a[++tot]=x;
}
inline void dfs(int i,int s1){
if(i>tot){
int Maxn=Max(s1,n/s1);
//printf("%lld\n",Maxn);
if(Maxn<ans2) ans1=n/Maxn,ans2=Maxn;
return ;
}
dfs(i+1,s1);
dfs(i+1,s1*a[i]);
}
template <typename T> void in(register T& a){
register T x=0,f=1;
register char c=getchar();
while(!isdigit(c)){
c=='-'?f=-1:f=1;
c=getchar();
}
while(isdigit(c)){
x=(x<<1)+(x<<3)+c-'0';
c = getchar();
}
a=x*f;
}
signed main(){
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
ans1=ans2=999999999999;
in(n);
primes();
work(n);
dfs(1,1);
printf("%lld %lld",ans1,ans2);
return o;
}