纪中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. Centos 7x 安装 Telegram MTproxy代理【完美可用】

    0x00 最近迷上了Telegram,也就是电报,觉得通过这个获取国外的新闻比较方便 可是我的VPS小机子不给力,一开始使用的Centos 6x,死活装不上去, 发现MTproxy不支持Centos ...

  2. 温故知新,.NET 重定向深度分析

    在早期的.NET Framework程序员心里,重定向Redirect其实分为两种: Response.Redirect: Response对象的Redirect方法提供了一种实现客户端重定向的方法 ...

  3. 4..部署场景2:带有遗留的Linux Bridge

    此场景描述了使用Linux bridge的ML2插件实现OpenStack网络服务的遗留(基本)实现. 遗留实现通过为常规(非特权)用户提供一种方法来管理一个项目中的虚拟网络,并包含以下组件:提供了自 ...

  4. 简单看看ThreadPoolExecutor原理

    线程池的作用就不多说了,其实就是解决两类问题:一是当执行大量的异步任务时线程池能够提供较好的性能,在不使用线程池时,每当需要执行异步任务是需要直接new一个线程去执行,而线程的创建和销毁是需要花销的, ...

  5. why NW NMM backup sqlserver failed and how to solve it

    A NW NMM backup sqlserver failed. wow , I realze that maybe I put too many database backup together ...

  6. Go语言实现:【剑指offer】跳台阶

    该题目来源于牛客网<剑指offer>专题. 一只青蛙一次可以跳上1级台阶,也可以跳上2级.求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果). 1阶:共1种跳法: 2阶 ...

  7. Go语言实现:【剑指offer】二叉搜索树的第k个的结点

    该题目来源于牛客网<剑指offer>专题. 给定一棵二叉搜索树,请找出其中的第k小的结点.例如,(5,3,7,2,4,6,8) 中,按结点数值大小顺序第三小结点的值为4. Go语言实现: ...

  8. postman之签名接口校验

    有些接口在传参时,需要先对接口的参数进行数据签名加密,如pinter项目的中的签名接口 ,该接口参数如下: {"phoneNum":"123434"," ...

  9. Spring Cloud(七):服务网关zuul过滤器

    上文介绍了Zuul的基本使用与路由功能,本文接着介绍Zuul的核心概念 -- Zuul过滤器(filter). Zuul的功能基本通过Zuul过滤器来实现(类比于Struts的拦截器,只是Struts ...

  10. post 两种方式 application/x-www-form-urlencoded和multipart/form-data

    本次主要涉及 application/x-www-form-urlencoded方式. postman访问方式如图: java代码实现: 首先使用maven作为第三方依赖管理: <depende ...