首页 > 代码库 > 2014.11.12模拟赛【最小公倍数】| vijos1047最小公倍数

2014.11.12模拟赛【最小公倍数】| vijos1047最小公倍数

 

最小公倍数(lcm.c/.cpp/.pas)

题目描述

    给定两个正整数,求他们的最小公倍数。

样例输入

28 12

样例输出

84

数据范围

对于40%数据:1<=a,b<=10^9

对于60%的数据:1<=a,b<=10^12

对于100%数据:1<=a,b<=10^100

 

提示:为了略微降低题目难度,增加以下条件:

1. 输入数据保证a>=b

2. 输入数据保证a、b没有前导0

3. 输入数据保证除了在两个正整数a、b之间的空格和行末换行符以外,不存在其他非数字字符

 

最后友情提醒:高精除高精写二分做法风味更佳

 

其实就是superlcm啦……

先算出gcd(a,b),然后lcm(a,b)=a*b/gcd(a,b)

40分是暴力,60分lcm(a,b)=a/gcd(a,b)*b,这样不会爆long long

100分就呵呵了,你只要写高精度减法、乘法、除法就好了

给现场怒写高精度还A了的hzwer跪了

这其实可以当成模板来用

#define mx 300#include<cstdio>#include<iostream>using namespace std; struct gaojing{     int len;     int a[mx+10];};//定义高精度非负数类型gaojing zero,one;inline void set0(gaojing &s){    s.len=1;    for (int i=1;i<=mx+5;i++)s.a[i]=0;}inline void inputn(gaojing &a){	set0(a);    char ch=getchar();    while (ch<‘0‘||ch>‘9‘)ch=getchar();      while (ch>=‘0‘&&ch<=‘9‘)      {          a.a[a.len++]=ch-‘0‘;        ch=getchar();    }    a.len--;      int change[mx+15];    for (int i=1;i<=a.len;i++)        change[i]=a.a[i];      for (int i=1;i<=a.len;i++)        a.a[i]=change[a.len-i+1];    while (a.a[a.len]==0)a.len--;}  inline void put(gaojing a){    for (int i=a.len;i>=1;i--)printf("%d",a.a[i]);    printf("\n");}inline bool operator < (const gaojing &a,const gaojing &b){	if (a.len<b.len)return 1;	if (a.len>b.len)return 0;	for (int i=a.len;i>=1;i--)	{		if (a.a[i]<b.a[i])return 1;		if (a.a[i]>b.a[i])return 0;	}	return 0;}inline bool operator == (const gaojing &a,const gaojing &b){	if (a.len!=b.len)return 0;	for (int i=a.len;i>=1;i--)	{		if (a.a[i]!=b.a[i])return 0;	}	return 1;}inline gaojing max(const gaojing &a,const gaojing &b){    if (a<b)return b;    else return a;}inline gaojing min(const gaojing &a,const gaojing &b){	if (a<b)return a;	else return b;} inline gaojing operator + (const gaojing &a,const gaojing &b){    gaojing c;set0(c);      int maxlen=max(a.len,b.len);          for (int i=1;i<=maxlen;i++)          {              c.a[i]=c.a[i]+a.a[i]+b.a[i];              if (c.a[i]>=10)              {                  c.a[i+1]+=c.a[i]/10;                c.a[i]%=10;            }        }          c.len=maxlen+4;          while (!c.a[c.len]&&c.len>1) c.len--;        return c;}inline gaojing operator - (const gaojing &a,const gaojing &b){	gaojing c;set0(c);	gaojing d;d=a;    for (int i=1;i<=b.len;i++)        {          c.a[i]=d.a[i]-b.a[i];          if (c.a[i]<0)          {              c.a[i]+=10;              int now=i+1;              while (!d.a[now])              {                  d.a[now]=9;                  now++;              }              d.a[now]--;          }        }    for (int i=b.len+1;i<=d.len;i++)c.a[i]=d.a[i];      c.len=d.len;      while (c.a[c.len]==0&&c.len>1)c.len--;    return c;}  inline gaojing operator * (const gaojing &a,const gaojing &b){    gaojing c;set0(c);    for(int i=1;i<=a.len;i++)          for (int j=1;j<=b.len;j++)            c.a[i+j-1]+=a.a[i]*b.a[j];        c.len=a.len+b.len+5;      for (int i=1;i<=c.len;i++)          {            c.a[i+1]+=c.a[i]/10;            c.a[i]%=10;          }        while (!c.a[c.len]&&c.len>1)c.len--;    return c;}inline void div_by_2(gaojing &a){	for (int i=a.len;i>=1;i--)	{		if (a.a[i]&1 && i!=1)a.a[i-1]+=10;		a.a[i]/=2;	}	while (!a.a[a.len]&&a.len>1)a.len--;}inline gaojing operator / (gaojing a,const gaojing &b){	gaojing l,r,ans;	set0(l);l.len=1;	set0(r);r=a;	set0(ans);ans.len=1;	while (l<r||l==r)	{		gaojing mid=l+r;		div_by_2(mid);		if(mid*b==a)return mid;		if(mid*b<a){ans=mid;l=mid+one;}		if(a<mid*b)r=mid-one;	}	return ans;}inline void chushihua(){	set0(zero);	zero.len=1;	set0(one);one.len=1;one.a[1]=1;}inline gaojing gcd(const gaojing &a,const gaojing &b){	if (b==zero)return a;	return gcd(b,a-a/b*b);}int main(){	gaojing a,b;	chushihua();	inputn(a);	inputn(b);	put(a/gcd(a,b)*b);}

  

2014.11.12模拟赛【最小公倍数】| vijos1047最小公倍数