我们来安利一个黑科技。(其实是Claris安利来的

比如我现在有一坨询问,每次询问两个不超过n的数的gcd。

n大概1kw,询问大概300w(怎么输入就不是我的事了,大不了交互库

http://mimuw.edu.pl/~kociumaka/files/stacs2013_slides.pdf

http://drops.dagstuhl.de/opus/volltexte/2013/3938/pdf/26.pdf

我们定义一个数k的一种因式分解k=k1*k2*k3为“迷之分解”当且仅当k1、k2、k3为质数或小于等于$\sqrt{k}$ 。

我们发现线筛的时候对于一个数x,设x最小的质因子为p,x/p=g,那么x的“迷之分解”可以通过g的“迷之分解”中三个数最小的一个乘上p得到。

证明似乎可以用数学归纳法证(然而我证不出来啊

然后对于每两个小于等于$\sqrt{n}$ 的数我们可以打一张gcd表出来。

最后如果我们要询问gcd(x,y),我们找到x的“迷之分解”,然后如果分解的一部分小于等于$\sqrt{n}$ 那就查表,否则那就是一个质数,分类讨论一下就行了。

伪代码:

UPD:实际测试了一下随机数据跑得并没有沙茶gcd快。可能是我实现的姿势不够优越(雾

大家可以测试一下跑gcd(5702887,9227465)这个算法比沙茶gcd不知道快到哪里去了

//跑得比谁都快的gcd?
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <string.h>
#include <vector>
#include <math.h>
#include <time.h>
#include <limits>
#include <set>
#include <map>
using namespace std;
const int N=;
const int sn=sqrt(N);
bool np[N+];
int ps[N+],pn=;
int cs[N+][];
void xs()
{
np[]=cs[][]=cs[][]=cs[][]=;
for(int i=;i<=N;i++)
{
if(!np[i]) {cs[i][]=cs[i][]=; cs[i][]=i; ps[++pn]=i;}
for(int j=;j<=pn&&i*ps[j]<=N;j++)
{
np[i*ps[j]]=;
int cm=cs[i][]*ps[j];
if(cm<cs[i][])
{
cs[i*ps[j]][]=cm;
cs[i*ps[j]][]=cs[i][];
cs[i*ps[j]][]=cs[i][];
}
else if(cm<cs[i][])
{
cs[i*ps[j]][]=cs[i][];
cs[i*ps[j]][]=cm;
cs[i*ps[j]][]=cs[i][];
}
else
{
cs[i*ps[j]][]=cs[i][];
cs[i*ps[j]][]=cs[i][];
cs[i*ps[j]][]=cm;
}
if(i%ps[j]);else break;
}
}
}
int gcdd[sn+][sn+];
void smgcd()
{
for(int i=;i<=sn;i++) gcdd[i][]=gcdd[][i]=i;
for(int i=;i<=sn;i++)
{
for(int j=;j<=i;j++) gcdd[i][j]=gcdd[j][i]=gcdd[i-j][j];
}
}
void pre_gcd() {xs(); smgcd();}
int gcd(int a,int b)
{
if(a>N||b>N)
{
puts("Fuck You\n");
return -;
}
int *x=cs[a],g=;
for(int i=;i<;i++)
{
int d;
if(x[i]<=sn) d=gcdd[x[i]][b%x[i]];
else if(b%x[i]) d=;
else d=x[i];
g*=d; b/=d;
}
return g;
}
int euclid_gcd(int x,int y)
{
while(y)
{
int t=x%y; x=y; y=t;
}
return x;
}
int tmd=-;
void gc()
{
if(tmd==-) tmd=clock();
else
{
printf("Passed: %dms\n",clock()-tmd);
tmd=-;
}
}
int main()
{
int seed=time();
//1kw个随机数测试
int ans;
printf("Euclid gcd...\n");
srand(seed);
gc();
ans=;
for(int i=;i<=;i++)
{
int a=(rand()*+rand())%N+,b=(rand()*+rand())%N+;
ans^=euclid_gcd(a,b);
}
printf("Ans = %d\n",ans);
gc();
printf("New gcd...\n");
srand(seed);
gc();
pre_gcd();
ans=;
for(int i=;i<=;i++)
{
int a=(rand()*+rand())%N+,b=(rand()*+rand())%N+;
ans^=gcd(a,b);
}
printf("Ans = %d\n",ans);
gc();
}

O(1) 查询gcd的更多相关文章

  1. HDU 5726 GCD

    传送门 GCD Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Problem ...

  2. Codeforces 914D - Bash and a Tough Math Puzzle 线段树,区间GCD

    题意: 两个操作, 单点修改 询问一段区间是否能在至多一次修改后,使得区间$GCD$等于$X$ 题解: 正确思路; 线段树维护区间$GCD$,查询$GCD$的时候记录一共访问了多少个$GCD$不被X整 ...

  3. 线段树 区间加 gcd 差分 小阳的贝壳

    小阳的贝壳 如果线段树要维护区间gcd 这个很简单,但是如果有了区间加,维护gcd 就比较麻烦了. 这个首先可以证明的是 gcd(x,y,z)=gcd(x,y-x,z-y)   这个可以推到 n 个 ...

  4. 2016 Multi-University Training Contest 1

    8/11 2016 Multi-University Training Contest 1 官方题解 老年选手历险记 最小生成树+线性期望 A Abandoned country(BH) 题意: 1. ...

  5. BZOJ5302 [HAOI2018]奇怪的背包 【数论 + dp】

    题目 小 CC 非常擅长背包问题,他有一个奇怪的背包,这个背包有一个参数 PP ,当他 向这个背包内放入若干个物品后,背包的重量是物品总体积对 PP 取模后的结果. 现在小 CC 有 nn 种体积不同 ...

  6. 树状数组 gcd 查询 Different GCD Subarray Query

    Different GCD Subarray Query Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K ( ...

  7. 2016暑假多校联合---GCD

    Problem Description Give you a sequence of N(N≤100,000) integers : a1,...,an(0<ai≤1000,000,000). ...

  8. GCD的深入理解

    GCD 深入理解(一) 本文由@nixzhu翻译至raywenderlich的<grand-central-dispatch-in-depth-part-1> 虽然 GCD 已经出现过一段 ...

  9. HDU5726 GCD(二分 + ST表)

    题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5726 Description Give you a sequence of N(N≤100, ...

随机推荐

  1. 好推二维码如何通过应用宝微下载支持微信自动打开APP下载?

    好推二维码 官网 http://www.hotapp.cn 1. 为什么使用应用宝微下载? APP下载二维码,通过微信扫描下载的时候,微信目前只支持应用宝微下载,才能在微信里直接打开下载,否则就需要在 ...

  2. 怎么查看Mac电脑的开机记录?

    可以使用last命令查看Mac电脑来看开机记录,同时也能查看关机记录. 首先打开mac的命令终端: 命令行终端敲入命令:last | grep reboot (查看开机时间记录) 命令行终端敲入命令: ...

  3. c中的数据类型、常量、变量

    一. 数据 1. 什么是数据 生活中时时刻刻都在跟数据打交道,比如体重数据.血压数据.股价数据等.在我们使用计算机的过程中,会接触到各种各样的数据,有文档数据.图片数据.视频数据,还有聊QQ时产生的文 ...

  4. 【Android】保存Fragment切换状态

    前言 一般频繁切换Fragment会导致频繁的释放和创建,如果Fragment比较臃肿体验就非常不好了,这里分享一个方法. 声明 欢迎转载,但请保留文章原始出处:)  博客园:http://www.c ...

  5. iOS带动画的环形进度条(进度条和数字同步)

    本篇写的是实现环形进度条,并带动画效果,要实现这些,仅能通过自己画一个 方法直接看代码 为了方便多次调用,用继承UIView的方式 .m文件 #import <UIKit/UIKit.h> ...

  6. 使用C/C++,赋值运算时发生的转换

    使用C/C++,赋值运算时发生的转换主要有以下四种情况 一: 两边类型不同: 结果: 自动完成类型转换! 二: 长数赋给短数: 结果: 截取长数的低位送给短数! 三: 短数赋给长数: 结果: 原来是什 ...

  7. 基础篇之 Create Type

    Create Type 的话呢,是创建一个自定义的数据类型,等于说为常用的数据类型建造一个别名的样纸.然后就可以通用当前数据库的当前架构.(当然了,一般来说我们都是使用dbo架构,所以都会无事前面那个 ...

  8. W3School-CSS 背景实例

    CSS 背景实例 CSS 实例 CSS 背景实例 CSS 文本实例 CSS 字体(font)实例 CSS 边框(border)实例 CSS 外边距 (margin) 实例 CSS 内边距 (paddi ...

  9. WIN 下的超动态菜单(一)

    WIN 下的超动态菜单(一)介绍 WIN 下的超动态菜单(二)用法 WIN 下的超动态菜单(三)代码 作者:黄山松,发表于博客园:http://www.cnblogs.com/tomview/     ...

  10. 开发Eclipse自定义控件

    摘自:http://www.ibm.com/developerworks/cn/opensource/os-eclipcntl/ 我们在开发自定义控件时主要考虑以下问题: 1. 自定义控件的绘制:通常 ...