纪中21日T3 2118. 最大公约数

(File IO): input:gcd.in output:gcd.out

时间限制: 1000 ms  空间限制: 262144 KB  具体限制

Goto ProblemSet

题目描述

给出两个正整数A,B,求它们的最大公约数。

输入

第一行一个正整数A。
第二行一个正整数B。

输出

在第一行输出一个整数,表示A,B的最大公约数。

样例输入

18
24 

样例输出

数据范围限制

在40%的数据中,1 ≤ A,B ≤ 10^6
在60%的数据中,1 ≤ A,B ≤ 10^18
在80%的数据中,1 ≤ A,B ≤ 10^100
在100%的数据中,1 ≤ A,B ≤ 10^1000

Solution

Algorithm1

正常的gcd(a,b)=gcd(b,a%b);

开unsigned long long可得六十分(应该不会超时)

Code1

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<queue>
#include<vector>
#define IL inline
using namespace std;
unsigned long long gcd(unsigned long long a,unsigned long long b)
{
return b==?a:gcd(b,a%b);
}
unsigned long long a,b;
int main()
{
cin>>a>>b;
cout<<gcd(a,b);
return ;
}

Attention1

函数也要开ULL(缩写)

别把“%”写成“-”,否则在相减前要先使得a>b

而且那样就变成更相减损法了

Algorithm2

gcd二进制法

先看看a,b是不是2的倍数

如果都是,gcd(a,b)=2*gcd(a/2,b/2);

如果a是,gcd(a,b)=gcd(a/2,b);

如果b是,gcd(a,b)=gcd(a,b/2);

如果都不是,gcd(a,b)=gcd(b,a%b)

最后一条=gcd(b,a-b)也可以

(为后面的高精度做铺垫)

Code2

 #include<iostream>
#include<iomanip>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<queue>
#include<vector>
#define IL inline
using namespace std;
IL unsigned long long gcdbin(unsigned long long a,unsigned long long b)
{
if(!b) return a;
if(!(a|)&&!(b|)) return *gcdbin(a>>,b>>);
if(!(a|)&&(b&)) return gcdbin(a>>,b);
if((a&)&&!(b|)) return gcdbin(a,b>>);
return gcdbin(b,a%b);
}
unsigned long long a,b;
int main()
{
freopen("rand_gcd.txt","r",stdin);
cin>>a>>b;
cout<<gcdbin(a,b);
return ;
}

Code2

Algorithm3

不压位的高精度

高精度求余数很麻烦(按位求会比较快)

套用更相减损法

同时特判:如果a,b小于19位,依然采用二进制的辗转相除。

Code3

在GMOJ上……

Code3

由于是普通的更相减损,一旦数位超过20使用高精,速度就会很慢很慢很慢……

60分~80分不等

Algorithm4

高精压位

核心算法与Algorithm3相同

Code4

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<queue>
#include<vector>
#define IL inline
using namespace std;
const int L=;
int a[L],b[L],t[L];
int times=;
string stra,strb;
bool fail;
IL bool cmp()
{
for(int i=L-;i>=;i--)
{
if(a[i]>b[i]) return ;
if(a[i]<b[i]) return ;
}
return ;
}
IL void minus()
{ }
IL void diva()
{
for(int i=L-;i>=;i--)
{
if(a[i]&) a[i-]+=;
a[i]>>=;
}
}
IL void divb()
{
for(int i=L-;i>=;i--)
{
if(b[i]&) b[i-]+=;
b[i]>>=;
}
}
IL void div2()
{
diva();
divb();
}
int main()
{
// freopen("gcd.in","r",stdin);
// freopen("gcd.out","w",srdout);
cin>>stra>>strb;
for(unsigned int i=;i<stra.size();i++)
a[i]=stra[stra.size()-i-];
for(unsigned int i=;i<strb.size();i++)
b[i]=strb[strb.size()-i-];
do{
if(!(a[]|)&&!(b[]|)){
times*=;
div2();
continue;
}
if(!(a[]|)&&(b[]&))
{
diva();
continue;
}
if((a&)&&!(b|))
{
divb();
continue;
} fail=;
for(int i=;i<L;i++)
{
if(a[i]&&b[i])//会不会出现0与非0交错出现呢?概率是(1/10)^L吧……
{
fail=;
break;
}
}
}while(fail);
bool zeroa;//为了避免交换,不能确定那个是0
for(int i=;i<L;i++)
{
if(a[i]){
zeroa=;
break;
}
if(b[i]){
zeroa=;
break;
}
}
bool flag=;
if(zeroa)
for(int i=;i<L;i++)
{
a[i]*=times;
a[i+]+=(a[i]>>)+(a[i]>>);
a[i]%=;
}
else
for(int i=;i<L;i++)
{
b[i]*=times;
b[i+]+=(b[i]>>)+(b[i]>>);
b[i]%=;
}
if(zeroa)
for(int i=L-;i>=;i--)
{
if(a[i]) flag=;
if(flag) cout<<a[i];
}
else
for(int i=L-;i>=;i--)
{
if(b[i]) flag=;
if(flag) cout<<b[i];
} return ;
}

Code4

Algorithm5

通过下面(最下面)的对拍发现,四种算法中,二进更相比普通更相更快(不是只有0.3毫秒么?)

高精(可以不压位)二进制更相减损术也不是很难打(而且判断也很快)

Algorithm6

之前是苦于没有时间打高精,终于在今天(2019-11-05 现在是00:17:29),我无意中点开了这篇题解,将我的高精度(甚至都没有压位)的模板稍作修改后边送上了“断头台”……

哈哈哈!

惊到我了!

Code6

由于是模板,所以代码较长。

 #include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std; bool insigma(char ch){
return ch=='-'||(''<=ch&&ch<='');
} const int maxn = ;
struct number{
int num[maxn];
int len;
bool fu; number(){//初始化
len=fu=;
memset(num,,sizeof(num));
} int updata_len(){//更新长度
for(int i=maxn-;i>=;i--) if(num[i]) return len=i+;
return len=;
} // /*
number operator= (int x){//隐式转换
fu=(x<);
num[]=abs(x);
if(x>) carry_bit();
if(x<-) back_space();
return *this;
}
// */
/*
number (int x){//有bug的构造函数 暂时用重载=替代
fu=(x<0);
num[0]=abs(x);
if(x>9) carry_bit();
if(x<-9) back_space();
}
*/ void input(){
// /*
string a;
cin>>a;
if(a[]=='-'){
fu=;
len=a.size()-;
for(unsigned int i=;i<a.size()-;i++) num[i]=a[a.size()-i-]-'';
}
else{
len=a.size();
for(unsigned int i=;i<a.size();i++) num[i]=a[a.size()-i-]-'';
} // */
/*
len=0;
char ch;
while(!insigma(ch=getchar()));
if(ch=='-')
fu=true;
else
num[len++]=ch-'0';
while(isdigit(ch=getchar())){
num[len++]=ch-'0';
}
int t;
for(int i=0;i<len;i++)
{
t=num[i];
num[i]=num[len-i-1];
num[len-i-1]=t;
}
*/
} void output(){
if(fu) cout<<"-";
bool flag=;
for(int i=len;i>;i--){
if(num[i]) flag=;
if(num[i]>) carry_bit();
if(flag) putchar(num[i]+'');//putchar加速
}
putchar(num[]+'');
} friend istream & operator>> (istream &in, number &obj);
friend ostream & operator<< (ostream &out, number &obj); int compare(number x){//2= 1> 0<
if(fu^x.fu){
if(fu) return ;
else return ;
}
for(int i=max(len,x.len);i>=;i--)
{
if(num[i]>x.num[i]) return !fu;//大于 (1)
if(num[i]<x.num[i]) return fu;//小于 (0)
}
return ;//相等
} //利用compare()重载比较运算符 bool operator> (number x){
return (compare(x)==);
} bool operator< (number x){
return (compare(x)==);
} bool operator>= (number x){
return !(*this<x);
} bool operator<= (number x){
return !(*this>x);
} bool operator== (number x){
return compare(x)==;
} bool operator!= (number x){
return compare(x)!=;
} number operator++ (){
num[]++;
if(num[]>) carry_bit();
return *this;
} number operator++ (int){
number save=*this;
++*this;
return save;
} number operator-- (){
num[]--;
if(num[]<) back_space();
return *this;
} number operator-- (int){
number save=*this;
num[]--;
if(num[]<) back_space();
return save;
} bool judge_zero(){
for(int i=maxn-;i>=;i--)
if(num[i]) return ;
return ;
} bool judge_non_zero(){
return !judge_zero();
} bool convert_bool(){
return !judge_zero();
} bool even(){
if(num[]%) return ;
return ;
} bool odd(){
if(num[]%) return ;
return ;
} void carry_bit(){
for(int i=;i<maxn;i++){
num[i+]+=num[i]/;
num[i]%=;
}
updata_len();
} void back_space(){
for(int i=;i<maxn;i++){
while(num[i]<) num[i]+=,num[i+]--;
}
} number operator+ (int x){
number newness=*this;
newness.num[]+=x;
if(newness.num[]>) newness.carry_bit();
return newness;
} number operator+ (number x){
number res=x;
for(int i=;i<maxn;i++)
{
res.num[i]+=num[i];
}
res.carry_bit();
return res;
} number operator+= (int x){
*this=(*this+x);
return *this;
} number operator+= (number x){
*this=*this+x;
return *this;
} number operator- (number x){
number i,j;
if(compare(x)) {i=*this,j=x;}
else {i=x,j=*this;}
for(int t=;t<maxn;t++)
{
i.num[t]-=j.num[t];
}
i.back_space();
return i;
} number operator-= (number x){
*this=*this-x;
return *this;
} number operator* (number x){
number sum;
sum.fu=fu^x.fu;
for(int i=;i<updata_len();i++)
for(int j=;j<x.updata_len();j++)
{
if(i+j>maxn-) continue;
sum.num[i+j]+=num[i]*x.num[j];
}
sum.carry_bit();
return sum;
} number operator*= (number x){
return *this=*this*x;
} number factor(){
number ans,t;
t.num[]=;
ans.num[]=;
for(;t<=*this;t.num[]+=,t.carry_bit())
ans*=t;
return ans;
} number division2(){
for(int i=maxn-;i>=;i--){
if(num[i]&&&i!=) num[i-]+=;
num[i]>>=;
}
return *this;
}
}; istream & operator>> (istream &in, number &obj)
{
string a;
in>>a;
if(a[]=='-'){
obj.fu=;
obj.len=a.size()-;
for(unsigned int i=;i<a.size()-;i++) obj.num[i]=a[a.size()-i-]-'';
}
else{
obj.len=a.size();
for(unsigned int i=;i<a.size();i++) obj.num[i]=a[a.size()-i-]-'';
}
if (!in) obj = number();
return in;
} ostream & operator<< (ostream &out, number &obj)
{
if(obj.fu) cout<<"-";
bool flag=;
for(int i=obj.len;i>;i--){
if(obj.num[i]) flag=;
if(obj.num[i]>) obj.carry_bit();
if(flag) out<<obj.num[i];
}
out<<obj.num[];
return out;
} number gcd_rec(number a,number b){
if(b.judge_zero()) return a;
return gcd_rec(b,a-b);
} number gcd(number a,number b){
if(a.judge_zero()) return a;
number t;
for(;;t=b,b=a-b,a=t)
if(b.judge_zero()) return a;
return a;
} number power(number a,number n){
number zero;
number c;c=;
for(;n>zero;n.division2(),a*=a) if(n.odd()) c*=a;
return c;
} int main()
{
freopen("gcd.in","r",stdin);
freopen("gcd.out","w",stdout);
number a,b,c;
cin>>a>>b;
c=gcd(a,b);
cout<<c;
return ;
}

Impression

如果你有兴趣……

#pragma GCC optimize(2)
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<queue>
#include<vector>
#define IL inline
using namespace std;
unsigned long long gcd(unsigned long long a,unsigned long long b)
{
return b==?a:gcd(b,a%b);
}
unsigned long long a,b;
int main()
{
freopen("rand_gcd.txt","r",stdin);
cin>>a>>b;
cout<<gcd(a,b);
return ;
}

gcd.cpp

#pragma GCC optimize(2)
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<queue>
#include<vector>
#define IL inline
using namespace std;
unsigned long long gx(unsigned long long a,unsigned long long b)
{
if(a<b) swap(a,b);
return b==?a:gx(b,a-b);
}
unsigned long long a,b;
int main()
{
freopen("rand_gcd.txt","r",stdin);
cin>>a>>b;
cout<<gx(a,b);
return ;
}

gx.cpp

#pragma GCC optimize(2)
#include<iostream>
#include<iomanip>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<queue>
#include<vector>
#define IL inline
using namespace std;
IL unsigned long long gcdbin(unsigned long long a,unsigned long long b)
{
if(!b) return a;
if(!(a|)&&!(b|)) return *gcdbin(a>>,b>>);
if(!(a|)&&(b&)) return gcdbin(a>>,b);
if((a&)&&!(b|)) return gcdbin(a,b>>);
return gcdbin(b,a%b);
}
unsigned long long a,b;
int main()
{
freopen("rand_gcd.txt","r",stdin);
cin>>a>>b;
cout<<gcdbin(a,b);
return ;
}

gcdbin

#pragma GCC optimize(2)
#include<iostream>
#include<iomanip>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<queue>
#include<vector>
#define IL inline
using namespace std;
IL unsigned long long gxbin(unsigned long long a,unsigned long long b)
{
if(!b) return a;
if(!(a|)&&!(b|)) return *gxbin(a>>,b>>);
if(!(a|)&&(b&)) return gxbin(a>>,b);
if((a&)&&!(b|)) return gxbin(a,b>>);
if(a<b) swap(a,b);
return gxbin(b,a%b);
}
unsigned long long a,b;
int main()
{
freopen("rand_gcd.txt","r",stdin);
cin>>a>>b;
cout<<gxbin(a,b);
return ;
}

gxbin.cpp

#pragma GCC optimize(2)
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<queue>
#include<vector>
#include<windows.h>
#include<ctime>
#define IL inline
using namespace std;
int main()
{
freopen("rand_gcd.txt","w",stdout);
srand(time(NULL));
cout<<(unsigned long long)rand()*rand()*rand()<<endl;
cout<<(unsigned long long)rand()*rand()*rand()<<endl;
return ;
}

rand_gcd.cpp

#pragma GCC optimize(2)
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<queue>
#include<vector>
#include<ctime>
#define IL inline
using namespace std;
int avg[];
int times;
int main()
{
system("random_gcd.exe");
int s1=clock();
system("gcd.exe");
int s2=clock();
system("gcdbin.exe");
int s3=clock();
system("gx.exe");
int s4=clock();
system("gxbin.exe");
int e=clock();
// cout<<"\n辗转相除:"<<s2-s1<<"ms\n";
// cout<<"二进辗转:"<<s3-s2<<"ms\n";
// cout<<"更相减损:"<<s4-s3<<"ms\n";
// cout<<"二进更相:"<<e-s4<<"ms\n";
avg[]+=s2-s1;
avg[]+=s3-s2;
avg[]+=s4-s3;
avg[]+=e-s4;
times++;
if(times>=)
{
system("cls");
cout<<"总计"<<times<<"组数据\n";
cout<<"平均用时:\n";
cout<<"辗转相除:"<<avg[]/(times*1.0)<<"ms\n";
cout<<"二进辗转:"<<avg[]/(times*1.0)<<"ms\n";
cout<<"更相减损:"<<avg[]/(times*1.0)<<"ms\n";
cout<<"二进更相:"<<avg[]/(times*1.0)<<"ms\n";
return ;
}
main();
return ;
}

gcd对拍.cpp

1000组数据运算结果如下

End

纪中21日T3 2118. 【2016-12-30普及组模拟】最大公约数的更多相关文章

  1. 洛谷P1880 [NOI1995]石子合并 纪中21日c组T4 2119. 【2016-12-30普及组模拟】环状石子归并

    洛谷P1880 石子合并 纪中2119. 环状石子归并 洛谷传送门 题目描述1 在一个圆形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石 ...

  2. 纪中21日c组模拟赛

    AWSL  AWSL  AWSL  AWSL AWSL  AWSL  AWSL  AWSL AWSL  AWSL  AWSL  AWSL AWSL  AWSL  AWSL  AWSL 题解传送 T1  ...

  3. 纪中21日c组T1 1575. 二叉树

    1575. 二叉树 (File IO): input:tree.in output:tree.out 时间限制: 1000 ms  空间限制: 262144 KB  具体限制   Goto Probl ...

  4. 纪中10日T3 2296. 神殿 bfs

    2296. 神殿 (File IO): input:temple.in output:temple.out 时间限制: 1500 ms  空间限制: 524288 KB  具体限制 Goto Prob ...

  5. 纪中21日c组T2 2117. 【2016-12-30普及组模拟】台风

    2117. 台风 (File IO): input:storm.in output:storm.out 时间限制: 1000 ms  空间限制: 262144 KB  具体限制 Goto Proble ...

  6. 纪中5日T3 1566. 幸运锁(lucky.pas/c/cpp)

    1566. 幸运锁(lucky.pas/c/cpp) 题目描述 有一把幸运锁,打开它将会给你带来好运,但开锁时需要输入一个正整数(没有前导0).幸运锁有一种运算,对于一个正整数,返回他的相邻两位数字间 ...

  7. 纪中17日T1 2321. 方程

    纪中17日T1 2321. 方程 (File IO): input:cti.in output:cti.out 时间限制: 1000 ms  空间限制: 262144 KB  具体限制   Goto ...

  8. 纪中10日T1 2313. 动态仙人掌

    纪中10日 2313. 动态仙人掌 (File IO): input:dinosaur.in output:dinosaur.out 时间限制: 1500 ms  空间限制: 524288 KB  具 ...

  9. 纪中23日c组T3 2161. 【2017.7.11普及】围攻 斐波那契数列

    2161. 围攻 (File IO): input:siege.in output:siege.out 时间限制: 1000 ms  空间限制: 262144 KB  具体限制   Goto Prob ...

随机推荐

  1. 三、Django学习之单表查询接口

    查询接口 all() 查询所有结果,结果是queryset类型 filter(**kwargs) and条件关系:参数用逗号分割表示and关系 models.Student.objects.filte ...

  2. 练习2-14 求奇数分之一序列前N项和 (15 分)

    练习2-14 求奇数分之一序列前N项和 (15 分) 本题要求编写程序,计算序列 1 + 1/3 + 1/5 + ... 的前N项之和. 输入格式: 输入在一行中给出一个正整数N. 输出格式: 在一行 ...

  3. 使用html及CSS实现在table中文字信息超过5个隐藏,鼠标移到时弹窗显示全部:

    使用html及CSS实现在table中文字信息超过5个隐藏,鼠标移到时弹窗显示全部: <!DOCTYPE html><html lang="en">< ...

  4. 上周 GitHub 热点速览 vol.07:GitHub 官方 CLI beta 版已发布

    摘要:GitHub Trending 上周看点,GitHub 官宣 CLI 已发布 beta 版,前端新晋高性能打包神器 esbuild 宣战 Webpack&Parcel,微软.Facebo ...

  5. Go语言实现:【剑指offer】把二叉树打印成多行

    该题目来源于牛客网<剑指offer>专题. 从上到下按层打印二叉树,同一层结点从左至右输出.每一层输出一行. 需要分层,二维数组. Go语言实现: /** * Definition for ...

  6. 《古剑奇谭3》千秋戏辅助工具(前端React制作)

    前言 一直身在武汉,基于众所周知的疫情原因,这个春节只能宅着. 不过其实这个春节是这些年来过得最爽的一个了. 没有鞭炮,不用四处跑,安安心心呆在家里玩玩游戏看看书写写代码,其实日子过得还是挺悠闲的. ...

  7. 数据算法 --hadoop/spark数据处理技巧 --(15.查找、统计和列出大图中的所有三角形 16.k-mer计数)

    十五.查找.统计和列出大图中的所有三角形 第一步骤的mr: 第二部mr: 找出三角形 第三部:去重 spark: 十六: k-mer计数 spark:

  8. .NET Core之单元测试(三):Mock框架Moq的使用

    编写一个API 新增一个接口 public interface IFoo { bool Ping(string ip); } 接口实现 public class Foo : IFoo { public ...

  9. python图片处理PIL

    一.PIL介绍 PIL中所涉及的基本概念有如下几个:通道(bands).模式(mode).尺寸(size).坐标系统(coordinate system).调色板(palette).信息(info)和 ...

  10. oracle-11g-R2监听文件配置

    客户端连接oracle数据库时出现如下错误: Listener refused the connection with the following error: ORA-, TNS:listener ...