GCD&&LCM的一些经典问题

1.1~n的所有数的最小公倍数:lightoj 1289  传送门

分析:素因子分解可知这个数等于小于1~n的所有素数的最高次幂的乘积

预处理1~n的所有质数,空间较大,筛选的时候用位图来压缩,和1~n所有

质数的乘积,剩下的就是找最高次幂的问题了。

代码如下:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#define PB push_back
#define MP make_pair
#define REP(i,n) for(int i=0;i<(n);++i)
#define FOR(i,l,h) for(int i=(l);i<=(h);++i)
#define DWN(i,h,l) for(int i=(h);i>=(l);--i)
#define IFOR(i,h,l,v) for(int i=(h);i<=(l);i+=(v))
#define CLR(vis) memset(vis,0,sizeof(vis))
#define MST(vis,pos) memset(vis,pos,sizeof(vis))
#define MAX3(a,b,c) max(a,max(b,c))
#define MAX4(a,b,c,d) max(max(a,b),max(c,d))
#define MIN3(a,b,c) min(a,min(b,c))
#define MIN4(a,b,c,d) min(min(a,b),min(c,d))
#define PI acos(-1.0)
#define INF 1000000000
#define LINF 1000000000000000000LL
#define eps 1e-8
#define LL long long
using namespace std;

const int maxn = 1e8+10;

typedef unsigned int UI;

UI tmp[5800000];
int vis[maxn/32+10];
int p[5800000],cnt;

void init(){
    cnt=0;
    p[0]=tmp[0]=2;
    cnt++;
    IFOR(i,3,maxn-1,2){
        if(!(vis[i/32]&(1<<(i%32)))){//用位图压缩节省空间
            p[cnt]=i;
            tmp[cnt]=tmp[cnt-1]*i;
            cnt++;
            IFOR(j,3*i,maxn-1,2*i) vis[j/32]|=(1<<(j%32));
        }
    }
}

UI solve(int n){
    int pos = upper_bound(p,p+cnt,n)-p-1;
    UI ans = tmp[pos];
    for(int i=0;i<cnt&&p[i]*p[i]<=n;i++){
        int  mul = p[i];
        int ff=p[i]*p[i];
        while(ff/mul==p[i]&&ff<=n){
            mul=mul*p[i];
            ff=ff*p[i];
        }
        ans=ans*(mul/p[i]);
    }
    return ans;
}

int main()
{
    init();
    int t,cas=1,n;
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        printf("Case %d: %u\n",cas++,solve(n));
    }
    return 0;
}

2,1~n中最小公倍数等于n的数的对数 lightoj 1236
传送门

很明显这些数都是 n 的约数,

然后n=p1^a1*p1^a2*p3^a3...*pn^an;

对这两个数素因子分解要使得的每一个素数ai的最高次等于ai,

因此对于每一个因子的可能方案就有 (ai+1)*2-1;

代码如下:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

const int maxn = 1e7+10;

int p[maxn/5],tot;
bool vis[maxn];
void init(){
    tot=0;
    memset(vis,0,sizeof(vis));
    for(int i=2;i<maxn;i++){
        if(!vis[i]){
            p[tot++]=i;
            for(int j=i+i;j<maxn;j+=i)
                vis[j]=1;
        }
    }
}

int main()
{
    init();
    int t,cas=1;
    scanf("%d",&t);
    while(t--){
        long long n;
        scanf("%lld",&n);
        long long ans = 1;
        for(int i=0;i<tot&&p[i]*p[i]<=n;i++){
            if(n%p[i]==0){
                long long cnt = 0;
                while(n%p[i]==0)cnt++,n/=p[i];
                ans=ans*(cnt*2+1);
            }
        }
        if(n>1) ans*=3;
        ans=ans/2+1;
        printf("Case %d: %lld\n",cas++,ans);
    }
    return 0;
}

3. 1~n中任意两对数的最大公约数之和 UVA 11426
传送门

我们设 f[n] = sigma(gcd(i , n)) 1<=i<n

那么 ans[n] = ans[n-1] + f[n];

在求f[n]的时候我们可以枚举gcd 然后f[n]+=gcd*phi(n/gcd);

代码如下:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

#define PB push_back
#define MP make_pair
#define REP(i,n) for(int i=0;i<(n);++i)
#define FOR(i,l,h) for(int i=(l);i<=(h);++i)
#define DWN(i,h,l) for(int i=(h);i>=(l);--i)
#define IFOR(i,h,l,v) for(int i=(h);i<=(l);i+=(v))
#define CLR(vis) memset(vis,0,sizeof(vis))
#define MST(vis,pos) memset(vis,pos,sizeof(vis))
#define MAX3(a,b,c) max(a,max(b,c))
#define MAX4(a,b,c,d) max(max(a,b),max(c,d))
#define MIN3(a,b,c) min(a,min(b,c))
#define MIN4(a,b,c,d) min(min(a,b),min(c,d))
#define PI acos(-1.0)
#define INF 1000000000
#define LINF 1000000000000000000LL
#define eps 1e-8
#define maxn  4000001
#define LL long long
using namespace std;

int phi[maxn];

LL ans[maxn];
LL f[maxn];
void init(){
    FOR(i,1,maxn-1) phi[i]=i;
    IFOR(i,2,maxn-1,2) phi[i]=phi[i]>>1;
    IFOR(i,3,maxn-1,2){
        if(phi[i]==i){
            IFOR(j,i,maxn-1,i)
            phi[j]=phi[j] -phi[j]/i;
        }
    }
}

void solve(){
    CLR(ans);
    init();
    FOR(i,1,maxn-1){
        IFOR(j,i+i,maxn,i)
            f[j]=f[j]+(LL)i*phi[j/i];
    }
    ans[1]=f[1];
    FOR(i,2,maxn-1) ans[i]=ans[i-1]+f[i];
}

int main()
{
    solve();
    int n;
    while(~scanf("%d",&n)&&n){
        printf("%lld\n",ans[n]);
    }
    return 0;
}
时间: 2024-09-29 21:02:32

GCD&&LCM的一些经典问题的相关文章

POJ 2429 GCD &amp; LCM Inverse

设答案为ans1,ans2 ans1=a1*gcd,ans2=a2*gcd,a1,a2互质 gcd*a1*b1=lcm,gcd*a2*b2=lcm a1*b1=lcm=(ans1*ans2)/gcd=a1*a2 综上所诉,a1=b2,a2=b1. 也就是说,ans1=gcd*k1,ans2=gcd*k2 要求k1,k2尽量接近,并且k1,k2互质,并且,k2*k2=lcm/gcd 需要用到Pollard_rho分解质因数,然后暴力搜索寻找k1,k2.用了kuangbin大神的Pollard_rh

Uva 11388 GCD LCM ( 数论 )

Uva  11388 GCD LCM( 数论 ) 题意: 求是否存在a,b 使得lcm(a,b) = L, gcd(a,b) = G,不存在输出-1,存在输出a,b,且a尽可能小 分析: 强行暴力是不可能的数据很大,要用llu,这里有两种思路 思路一: 由题意可知 a*b = G*L 保证a = G的倍数的情况下,枚举a再判断G*L能否整除a,最后判断b是否为a的倍数.a从G开始扫到sqrt(G*L) //输入两个整数G,L //找出a,b 使得 gcd(a,b) = G lcm(a,b) =

UVA - 11388 GCD LCM

II U C   ONLINE   C ON TEST   2 008 Problem D: GCD LCM Input: standard input Output: standard output The GCD of two positive integers is the largest integer that divides both the integers without any remainder. The LCM of two positive integers is the

uva 11317 - GCD+LCM(欧拉函数+log)

题目链接:uva 11317 - GCD+LCM 题目大意:给定n,求出1~n里面两两的最大公约的积GCD和最小公倍数的积LCM,在10100进制下的位数. 解题思路:在n的情况下,对于最大公约数为i的情况又phi[n/i]次.求LCM就用两两乘积除以GCD即可. #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; ty

POJ 2429 GCD &amp; LCM Inverse (大数分解)

GCD & LCM Inverse 题目:http://poj.org/problem?id=2429 题意: 给你两个数的gcd和lcm,[1, 2^63).求a,b.使得a+b最小. 思路: lcm = a * b / gcd 将lcm/gcd之后进行大数分解,形成a^x1 * b^x2 * c^x3-- 的形式,其中a,b,c为互不相同的质数.然后暴力枚举即可. 代码: #include<map> #include<set> #include<queue>

poj 2429 GCD &amp; LCM Inverse 【java】+【数学】

GCD & LCM Inverse Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 9928   Accepted: 1843 Description Given two positive integers a and b, we can easily calculate the greatest common divisor (GCD) and the least common multiple (LCM) of a a

POJ 2429 GCD &amp; LCM Inverse(Pollard_Rho+dfs)

[题目链接] http://poj.org/problem?id=2429 [题目大意] 给出最大公约数和最小公倍数,满足要求的x和y,且x+y最小 [题解] 我们发现,(x/gcd)*(y/gcd)=lcm/gcd,并且x/gcd和y/gcd互质 那么我们先利用把所有的质数求出来Pollard_Rho,将相同的质数合并 现在的问题转变成把合并后的质数分为两堆,使得x+y最小 我们考虑不等式a+b>=2sqrt(ab),在a趋向于sqrt(ab)的时候a+b越小 所以我们通过搜索求出最逼近sqr

数论——gcd&amp;&amp;lcm

gcd(a, b),就是求a和b的最大公约数 lcm(a, b),就是求a和b的最小公倍数 然后有个公式 a*b = gcd * lcm     ( gcd就是gcd(a, b), ( ????? ) 简写你懂吗) 解释(不想看就跳过){ 首先,求一个gcd,然后... a / gcd 和 b / gcd 这两个数互质了,也就是 gcd(   a / gcd ,b / gcd  )  =  1,然后... lcm = gcd *  (a / gcd) * (b / gcd) lcm = (a *

POJ5429 GCD &amp; LCM Inverse

GCD & LCM Inverse Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 9913   Accepted: 1841 Description Given two positive integers a and b, we can easily calculate the greatest common divisor (GCD) and the least common multiple (LCM) of a a