特别说明: 为了避免以后搬家时的麻烦, 这里的文章继续沿用csdn的风格和分类好了~

Emmmm这个题是一道高精度的模板题啊~

既然是高精度的裸题, 那我们这些懒人当然是选择:用python啦~ 懒癌晚期

你看这不就做完了么←_←

a=input()
b=input()
while(b):
c=b
b=a%b
a=c
print a

当然这份代码并不能在luogu上AC 应该是数据出锅了.

(当然也不能算是出锅, 只是不太符合题目中说的输入格式而已...刻意卡python

(当然还是有一些python党摸清了读入的规律然后卡过去了 好像rank1就是python吧

不过毕竟是一道省选题, 如果省选真的碰到了总不能用python写吧(说好的遇到高精的题分就不要了呢

而且还可以锻炼码力(最后发现并没有

所以决定用c++写一发.

而作为STL依赖症的重度患者, 这次的代码直接上了一份

typedef vector<int> bignum;

不过其实是很方便的_(:з」∠)_ vector莫名其妙的实用, 经常跑得比数组还快, 不知道是怎么做到的.

然后如果真的按照上面python的代码, 那我们要写一个高精取模. 然而我并不会写.

这时候就需要用到我们中华民族老祖宗的智慧了——"更相减损之术"!!!

不过单纯的不优化的更相减损之术是很慢滴, 亲测在不压位的情况下使用可以得到40pts.

我们可以考虑一个简单易行的, 看上去也很显然的方法:

我们进行一波分类讨论:

  • \(a,b\)都是偶数, 那么\(gcd(a,b)=2gcd(\frac a2,\frac b2)\);
  • \(a,b\)中有且只有一个偶数, 假如是\(a\), 那么\(gcd(a,b)=gcd(\frac a2,b)\), 是\(b\)的话同理;
  • \(a,b\)都是奇数, 那就更相减损, \(gcd(a,b)=gcd(a-b,b)\).

这样的话我们迭代一波(注意不要递归, 递归超级损效率)就可以做了. 我们要做的操作有:

0. 输入

  1. 判断奇偶
  2. 减法
  3. 除2
  4. 乘2
  5. 输出

    这些都不是很难.. 我们分别做一下就好了.

    这样亲测我们已经能拿到70pts了.

那剩下30pts怎么找呢? 压位啊~

没有试压更少的位, 但是压4位已经可以跑得过了...

压8位的效率似乎提高了一丢丢, 但是还是挺慢的..

一定是我这个人自带大常数, 无数事实都证明了这一点(明明是你整天用STL...

然后就是代码了, 可以看到里面有很多实现是挺愚蠢的...(要不然为啥跑得慢呢←_←

这是压8位的

// luogu-judger-enable-o2
#include <cstdio>
#include <string>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1e8;
typedef vector<int> bignum;
inline int gcd(int a, int b) {
if (!b) return a;
return gcd(b, a%b);
}
inline bignum read() {
bignum a; string s, ss; cin >> s; reverse(s.begin(),s.end());
while (s.size() > 8) {
ss = s.substr(0, 8);
//a.push_back(ss[0] + ss[1] * 10 + ss[2] * 100 + ss[3] * 1000 - 48 * 1111);
int t = 1, tt = 0;
for (int i = 0; i < 8; ++i, t *= 10)
tt += (ss[i] - 48)*t;
a.push_back(tt);
s = s.substr(8, s.size());
} int b = 0; reverse(s.begin(), s.end());
for (int i = 0; i < s.size(); ++i)
b = b * 10 + s[i] - 48;
a.push_back(b);
return a;
}
inline void output(bignum a) {
int i = a.size() - 1;
printf("%d", a[i]);
if (!i) return;
for (--i; i >= 0; --i)
printf("%08d", a[i]);
}
inline bool iseven(bignum a) {
return !(*a.begin() & 1);
}
inline bool iszero(bignum a) {
return a.size() == 1 && *a.begin() == 0;
}
inline bool bigger(bignum a, bignum b) {
if (a.size() > b.size()) return 1;
if (a.size() < b.size()) return 0;
for (int i = a.size() - 1; i >= 0; --i) {
if (a[i] > b[i]) return 1;
if (a[i] < b[i]) return 0;
}
return 0;
}
inline void delzero(bignum& a) {
while (a.size() > 1) {
bignum::iterator it = --a.end();
if (*it) break;
a.erase(it);
it = --a.end();
}
}
inline void sub(bignum &a, bignum b) {
int i;
for (i = 0; i < b.size(); ++i) {
if (a[i] < b[i])
--a[i + 1], a[i] += N;
a[i] = a[i] - b[i];
}
while (i < a.size() && a[i] < 0)
{
a[i] += N;
++i;
--a[i];
}
delzero(a);
}
inline void half(bignum &a) {
for (int i = a.size() - 1; i >= 0; --i) {
if (a[i] & 1)
a[i - 1] += N;
a[i] = a[i] >> 1;
}
delzero(a);
}
inline void doubled(bignum& a) {
for (int i = 0; i < a.size(); ++i) {
a[i] <<= 1;
if (i > 0 && a[i - 1] >= N) a[i - 1] -= N, ++a[i];
}
bignum::iterator it = --a.end();
if (*it >= N) *it -= N, a.push_back(1);
}
int main() {
bignum a = read(), b = read(); int c = 0;
while (1) {
if (bigger(b, a)) swap(a, b);
if (iszero(b)) break;
if (iseven(a) && iseven(b)) {
half(a); half(b); ++c;
}
else if (iseven(a)) half(a);
else if (iseven(b)) half(b);
else sub(a, b);
}
for (; c; --c)
doubled(a);
output(a);
}

这是压4位的(其实差不多, 大约只有输入输出改了的样子)

#include <cstdio>
#include <string>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1e4;
typedef vector<int> bignum;
inline int gcd(int a, int b) {
if (!b) return a;
return gcd(b, a%b);
}
inline bignum read() {
bignum a; string s, ss; cin >> s; reverse(s.begin(),s.end());
while (s.size() > 4) {
ss = s.substr(0, 4);
a.push_back(ss[0] + ss[1] * 10 + ss[2] * 100 + ss[3] * 1000 - 48 * 1111);
s = s.substr(4, s.size());
} int b = 0; reverse(s.begin(), s.end());
for (int i = 0; i < s.size(); ++i)
b = b * 10 + s[i] - 48;
a.push_back(b);
return a;
}
inline void output(bignum a) {
int i = a.size() - 1;
printf("%d", a[i]);
if (!i) return;
for (--i; i >= 0; --i)
printf("%04d", a[i]);
}
inline bool iseven(bignum a) {
return !(*a.begin() & 1);
}
inline bool iszero(bignum a) {
return a.size() == 1 && *a.begin() == 0;
}
inline bool bigger(bignum a, bignum b) {
if (a.size() > b.size()) return 1;
if (a.size() < b.size()) return 0;
for (int i = a.size() - 1; i >= 0; --i) {
if (a[i] > b[i]) return 1;
if (a[i] < b[i]) return 0;
}
return 0;
}
inline void delzero(bignum& a) {
while (a.size() > 1) {
bignum::iterator it = --a.end();
if (*it) break;
a.erase(it);
it = --a.end();
}
}
inline void sub(bignum &a, bignum b) {
int i;
for (i = 0; i < b.size(); ++i) {
if (a[i] < b[i])
--a[i + 1], a[i] += N;
a[i] = a[i] - b[i];
}
while (i < a.size() && a[i] < 0)
{
a[i] += N;
++i;
--a[i];
}
delzero(a);
}
inline void half(bignum &a) {
for (int i = a.size() - 1; i >= 0; --i) {
if (a[i] & 1)
a[i - 1] += N;
a[i] = a[i] >> 1;
}
delzero(a);
}
inline void doubled(bignum& a) {
for (int i = 0; i < a.size(); ++i) {
a[i] <<= 1;
if (i > 0 && a[i - 1] >= N) a[i - 1] -= N, ++a[i];
}
bignum::iterator it = --a.end();
if (*it >= N) *it -= N, a.push_back(1);
}
int main() {
bignum a = read(), b = read(); int c = 0;
while (1) {
if (bigger(b, a)) swap(a, b);
if (iszero(b)) break;
if (iseven(a) && iseven(b)) {
half(a); half(b); ++c;
}
else if (iseven(a)) half(a);
else if (iseven(b)) half(b);
else sub(a, b);
}
for (; c; --c)
doubled(a);
output(a);
}

嗯, 就这样吧, 完结撒花✿✿ヽ(°▽°)ノ✿

【学术篇】SDOI2009 SuperGCD的更多相关文章

  1. BZOJ 1876: [SDOI2009]SuperGCD

    1876: [SDOI2009]SuperGCD Time Limit: 4 Sec  Memory Limit: 64 MBSubmit: 3060  Solved: 1036[Submit][St ...

  2. bzoj 1876 [SDOI2009]SuperGCD(高精度+更相减损)

    1876: [SDOI2009]SuperGCD Time Limit: 4 Sec  Memory Limit: 64 MBSubmit: 2384  Solved: 806[Submit][Sta ...

  3. BZOJ 1876: [SDOI2009]SuperGCD( 更相减损 + 高精度 )

    更相减损,要用高精度.... --------------------------------------------------------------- #include<cstdio> ...

  4. 【BZOJ1876】[SDOI2009]SuperGCD(数论,高精度)

    [BZOJ1876][SDOI2009]SuperGCD(数论,高精度) 题面 BZOJ 洛谷 题解 那些说数论只会\(gcd\)的人呢?我现在连\(gcd\)都不会,谁来教教我啊? 显然\(gcd\ ...

  5. 【学术篇】SDOI2009 学校食堂

    传送门~ 题目大意 先分析\((x\ or\ y)-(x\ and\ y)\), 就是\(x\)和\(y\)中存在的1减去\(x\)和\(y\)中相同的1 *那不就是\(x\ xor\ y\)么←_← ...

  6. 【学术篇】SDOI2009 最优图像

    又是一道辣鸡卡常数题…. luogu上有些题的时限还是有毒的… 最后也只能靠O2过掉了… 不过给我原题当时的2s我随便过给你看嘛, 哪怕评测姬慢50%都没关系的.. 贴一下codevs的截图… 你看最 ...

  7. 【学术篇】51nod 1238 最小公倍数之和

    这是一道杜教筛的入(du)门(liu)题目... 题目大意 求 \[ \sum_{i=1}^n\sum_{j=1}^nlcm(i,j) \] 一看就是辣鸡反演一类的题目, 那就化式子呗.. \[ \s ...

  8. 【学术篇】一些水的不行的dp

    最近做了几道非常水非常水的dp...... 之后刷的一些水dp也会写在这里...... 此篇题目难度不递增!!! Emmmm....... 1.luogu1043数字游戏 以前看过这个题几遍,没做这个 ...

  9. 【学术篇】luogu2184贪婪大陆

    题目在这里哦, 戳一下就可以了~ 题目大意: 支持两种操作,区间添加一种新元素,查询区间颜色种数.. 题目标签是线段树啊,我也本来想写一个线段树,后来写不出来……(我太弱了orz) 然后就草率地看了看 ...

随机推荐

  1. React-native 关于键盘遮挡界面问题

    //引入 KeyboardAvoidingView import { KeyboardAvoidingView } from 'react-native'; //使用 KeyboardAvoiding ...

  2. Python之删除字符串中不需要的字符

    简单的 str="---你好=====" print(str.strip("-=")) # 你好 从文件中读取多行数据,可以用生成器表达式 with open( ...

  3. aarch64 架构 交叉编译 tcpdump

    1. 下载 tcpdump 源码 地址 :http://www.tcpdump.org/    (4.9.2) tcpdump 依赖 libpcap  源码 地址 : http://www.tcpdu ...

  4. Linux设置chrome缓存至内存,及开关机同步

    默认chrome缓存位置在~/.cache/google-chrome中,磁盘io很多.为减少磁盘io,保护磁盘同时加快chrome速度,可设置缓存使用内存盘,缺点是重启后缓存丢失,所以这里可以使用脚 ...

  5. LinkedBlockingQueue 学习

    LinkedBlockingQueue 链表队列,其元素构成为: static class Node<E> { E item; Node<E> next; Node(E x) ...

  6. vue element-ui NavMenu错位问题

    原因:子菜单全部打开后太长超过100% 解决方法:设置只能点击打开当前的菜单

  7. Vivado利用IP自带的示例工程和仿真

    有时候想查看IP的特性和功能,又不想自己写testbench,Vivado自带的IP示例工程就能派上用场,原来一直不知道怎么打开IP的示例工程 第一步:在原有的工程中新建IP,按照你想要的IP属性,例 ...

  8. Django 自定义 admin

    为 model 自定义显示 label是这个Field如果在form中的话会显示的.而verbose_name在form中不会显示.只是作为一种说明而已 callable()   -->  是否 ...

  9. ArrayList,LinkedList,Vector集合的认识

    最近在温习Java集合部分,花了三天时间读完了ArrayList与LinkedList以及Vector部分的源码.之前都是停留在简单使用ArrayList的API,读完源码看完不少文章后总算是对原理方 ...

  10. AcWing 203. 同余方程 (线性同余方程)打卡

    求关于x的同余方程 ax ≡ 1(mod b) 的最小正整数解. 输入格式输入只有一行,包含两个正整数a,b,用一个空格隔开. 输出格式输出只有一行,包含一个正整数x,表示最小正整数解. 输入数据保证 ...