纪中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. 探究HashMap1.8的扩容

    扩容前 扩容后 机制 else { // preserve order Node<K,V> loHead = null, loTail = null;//低指针 Node<K,V&g ...

  2. 一次DB故障引起的反思和MySQL Operator选型

    前言 在一次数据库故障后,我们发现业务库会根据业务的等级会划分多个 MySQL 实例,许多业务库会同时属于一个 MySQL 实例,当一个库引发问题后整个实例的状态是不可控的.从而导致这个实例上的所有业 ...

  3. Sqli-Labs 闯关 less 42-49

    Less 42 这一关一进去看着像前面的二次注入.发现也注入不了.. 我们观察代码发现这一关用的是堆叠注入. 登陆的这里可以看到login_password登陆的时候并没有使用mysqli_real_ ...

  4. yukongDSRM账户安全防护

    一.DSRM简介 1.DSRM(Diretcory Service Restore Mode,目录服务恢复模式)是windows域环境中域控制器的安全模式启动选项.域控制器的本地管理员账户也就是DSR ...

  5. C++用rand()和srand()生成随机数

    内容来自<编程实战宝典> 首先来看函数原型 int rand(void); void srand(unsigned int seed); 1.rand()函数不需要任何参数,直接返回一个随 ...

  6. MapReduce清洗数据进行可视化

    继上篇第一阶段清洗数据并导入hive 本篇是剩下的两阶段 2.数据处理: ·统计最受欢迎的视频/文章的Top10访问次数 (video/article) ·按照地市统计最受欢迎的Top10课程 (ip ...

  7. python学习(5)写一个二分算法的程序

    把之前学习的做一个小结.之前看二分查找法,只能是似而非地看懂大概.现在用这么多天的知识积累已经可以自己写了. 而且在算法书的基础上,把需要找的数字做一个人机互动操作. 另外,初步接触到了 __name ...

  8. json-server的简单使用

    json-server是一个在前端本地运行,可以存储json数据的server(服务器),该服务器只支持 get 方法获取,不支持 post 方法获取,使用express工具可以使用post方法. V ...

  9. javascript console对象 常用的方法

    console对象 var o = {name:'3'} console.assert(o.name === '3', "name 的值应该为:string 3"); consol ...

  10. shell使用变量的值,获取一个新的变量名的值

    [root@localhost ~]# cat s2.sh #!/bin/bash color_name="red" red=31 color=`eval echo '$'&quo ...