ACM数论基础 详细整理

目录

质数

质数的判定

试除法

MillerRobbin(米勒罗宾素数测试)

素数筛法

埃氏筛

线性筛

区间筛

Prime Distance 

HDU6069 Counting Divisors(区间分解质因数)

阶乘分解

ural1055 Combinations

约数

算术基本定理的扩展

数值分块

BZOJ1257 余数之和

BZOJ2956 模积和

最大公约数

欧几里得算法

区间GCD

HDU 5726 GCD

HDU 5869 Different GCD Subarray Query

欧拉函数

POJ2478 Farey Sequence

POJ3090 Visible Lattice Points

POJ2480 Longge's problem

BZOJ 4804 欧拉心算   心酸

HDU5780 gcd

HDU4676 Sum Of Gcd

同余

同余类

剩余系

POJ2773 Happy 2006

欧拉定理

欧拉定理推论

UVA106992 Huge Mods

HDU2837 Calculation

裴蜀定理

扩展欧几里得算法

POJ2115 Looooops

POJ1061 青蛙的约会

同余不等式

POJ3530 A Modular Arithmetic Challenge

线性同余方程组

中国剩余定理

非互质线性同余方程组

POJ2891 Strange Way to Express Integers

GCD Table

高次同余方程

BSGS算法

bzoj2242  [SDOI2011]计算器

原根与指标

例题代码

Prime Distance 代码

Counting Divisors代码

Combinations代码

余数之和代码

模积和代码

斐波那契公约数代码

GCD代码 

Different GCD Subarray Query代码

Farey Sequence代码

Visible Lattice Points代码

Longge's problem代码

欧拉心算  代码

gcd代码

Sum Of Gcd代码

Happy 2006代码

Huge Mods代码

Calculation代码

Looooops代码

青蛙的约会代码

A Modular Arithmetic Challenge代码

Strange Way to Express Integers代码

GCD Table代码

 [SDOI2011]计算器代码


质数

质数的判定

 

试除法

若一个正整数 N 为合数,则一定存在一个能整除 N 的数字  2 \leqslant T\leq \sqrt{N}

 

MillerRobbin(米勒罗宾素数测试)

大于2的素数n,存在n-1=2^s*d,d为奇数

以下任一条件成立,n为素数,a为任意整数

a^d\equiv 1\mod n

a^(2^r*d)\equiv-1\mod n     0\leq r\leq s-1

typedef long long LL;
bool check(LL a, LL n) {
	LL m = n - 1, x, y;
	int i, j = 0;
	while (~m & 1)m >>= 1, j++;
	x = quickpow(a, m, n);		//快速幂
	for (i = 1; i <= j; x = y, i++) {
		y = quickpow(x, 2, n);
		if (y == 1 && x != 1 && x != n - 1)
			return true;
	}
	return y != 1;
}
bool miller_rabin(int times, int n) {
	LL a;
	if (n == 1)return false;
	if (n == 2) return true;
	if (~n & 1)return false;
	while (times--)
		if (check(rand() % (n - 1) + 1, n))
			return false;
	return true;
}

 

素数筛法

 

埃氏筛

任意x的倍数都不是素数

 

线性筛

埃式筛法对同一个合数多次标记导致耗时非线性,比如6=2*3=3*2

线性筛法通过唯一标记合数的方式来优化埃氏筛

for (int i = 2; i <= N; i++) {
	if (!vis[i])prime[cnt++] = i;
	for (int j = 0; j < cnt&&prime[j] * i <= N; j++) {
		vis[prime[j] * i] = true;
		if (i%prime[j] == 0)
			break;
	}
}

 

区间筛

一个合数 n 一定包含一个不超过 \sqrt{n} 的质因数

用筛法求出 \sqrt{Max} 以内的质数

用这些质数去标记 [L,R] 中的合数,未被标记的就是质数

const int maxm = 1000000;
bool v[maxm];
void interval_sieve(int l, int r) {
    memset(v,0,sizeof(v));
	if (l == 1)v[0] = true;
	for (int i = 0; i < cnt; i++) {
		for (int j = (l - 1) / prime[i] + 1; j <= r / prime[i]; j++) {
			if (j > 1) v[prime[i] * j - l] = true;
		}
	}
}

Prime Distance 

给定整数L,R,求区间相邻两个质数的差最大是多少?

板子题

 

HDU6069 Counting Divisors(区间分解质因数)

\sum_{i=1}{d(i^k)}\mod998244353

积性函数 x=p1^c1*p2^c2*---*pn^cn

因子数 d(x)=(c1+1)*(c2+1)---*(cn+1)

d(x^k)=(c1*k+1)*(c2*k+1)*---*(cn*k+1)

本题要用到区间筛法对L-R分解质因数

 

阶乘分解

阶乘 N!中包含质因子 x 的个数为\frac{N}{x}+\frac{N}{x^2}+\cdots+\frac{N}{x^n}

 

ural1055 Combinations

 求 Cm n (1 ≤n,m≤ 5∗105) 的不同质因子个数

C\binom{n}{m}=\frac{n!}{(n-m)!*m!}

分别求分子质因子个数和分母质因子个数,若分子个数比分母多则有效

 

约数

 

算术基本定理的扩展

约数个数=(C1+1)*(C2+1)+----+(Cn+1)

约数之和=(1+p_{1}+p_{1}^2+\cdots+p_{1}^c_{1})+(1+p_{2}+p_{2}^2+\cdots+p_{2}^c_{2})+\cdots+(1+p_{n}+p_{n}^2+\cdots+p_{n}^c_{n})

 

数值分块

 

BZOJ1257 余数之和

给定正整数n,k,计算

 k \mod 1 + k \mod 2 + k \mod 3 + --- + k \mod n

k \mod i = k - k / i * i

i<\sqrt(k)时,k/i最多只有\sqrt{k}个取值

i>\sqrt{k}时,k/i最多只有\sqrt{k}个取值

综上最多只有2\sqrt{k}个取值,且数值单调递减,可以数值分块

 

BZOJ2956 模积和

\sum_{i=1}^{n}\sum_{j=1}^{m}((n \mod i)*(m \mod j)) (i \neq j) 

=\sum_{i=1}^{n} (n\mod i)*\sum_{j=1}^{m}(m \mod i)-\sum_{i=1}^{min(n,m)}(n \mod i)*(m \mod i)

第一项与第二项与上题同

=\sum_{i=1}^{min(n,m)}(n-n/i*i)*(m-m/i*i)

=\sum_{i=1}^{min(n,m)}(n*m-m*n/i*i-n*m/i*i+n/i*i*m/i*i)

 

最大公约数

\gcd (Fib(n),Fib(m))=\gcd(Fib(n-m),Fib(m))

\gcd(m^a,n^a)=\gcd(m,n)^a

gcd(a^m-b^m,a^n-b^n)=a^{gcd(m,n)}-b^{gcd(m,n)}(a,b互质)

 

欧几里得算法

gcd(a.b)=gcd(b,a\mod b)

设 a = q∗b+r,其中 r = a mod b

对于 a,b 的任意公约数 d,d|a,d|q*b

则 d|(a-q*b),即 d|r

int gcd(int a,int b){
    return b? gcd(b,a%b):a;}
}

 

区间GCD

当固定区间的右端点,区间左端点越小,区间的GCD就越小,区间GCD的变化次数至多等于右端点的质因子数

a1=1,           a2=2,          a3=4,                a4=6 

(4,4)=6->(4,3)=2->(4,2)=2->(4,1)=1

从小到大枚举右端点,计算左端点的分界线l[j],表示对于右端点i,左端点属于[j,l[j]]时区间gcd都是相同的

l[4]=4:gcd(j,4)=4(4\leq j\leq 4)

l[3]=2:gcd(j,4)=2(2\leq j\leq 3 )

l[1]=1:gcd(j,4)=1(1\leq j\leq 1 )

在枚举i的过程中,可以利用右端点在i-1l数组的计算结果,因为区间内多一个数字时,区间GCD的段数单调不增,可以通过右端点在i-1时候的分段合并得到

a5=9

l[5]=5:gcd(j,5)=9

l[4]=4:gcd(j,4)=3

l[3]=1:gcd(j,3)=1

复杂度(nlogn)(nlogn)

//a[i]为数组
//l[j]表示l[j]-j的区间gcd相同
//v[j]表示l[j]-j的区间gcd的值
for (int i = 1; i <= n; i++) {
	for (v[i] = a[i], j = l[i] = i; j; j = l[j] - 1) {    //通过l[j]移动
		v[j] = gcd(v[j], a[i]);
		while (l[j] > 1 && gcd(a[i], v[j] - 1) == gcd(a[i], v[j]))    //若两个区间gcd相同则合并
			l[j] = l[l[j] - 1];
	}
}

HDU 5726 GCD

给出数组a,询问L,R的区间gcd的值和与L,R区间gcd相同的组数

枚举i的右端点,将所有的l[j]和v[j]分别存储(本题相同值的组数要开longlong!!!)

 

HDU 5869 Different GCD Subarray Query

求L-R区间内区间gcd的值的数量

转化为求区间内颜色数量的问题,可以用离线树状数组或者主席树做,不会的可以看道例题学习下,洛谷 HH的项链

那么这题需要考虑的是怎么把区间的颜色转化到点上?

我们通过区间gcd可以知道L【j】- j的颜色,即只要包含右边界,就可以取到x

所以增加一个区间,相当于j点增加一种颜色

 

欧拉函数

欧拉函数 ϕ(N):1 到 N 中与 N 互质的数字个数

\Theta (N)=N*\frac{p_{1}}{p_{1}-1}*\frac{p_{2}}{p_{2}-1}*\cdots*\frac{p_{n}}{p_{n}-1}

gcd(n,m)=1->\Theta (n*m)=\Theta(n)*\Theta(m)

对于质数p,\Theta (p)=p-1   

若a为质数,\Theta(b*a)=\Theta(b)*a(b\mod a==0)

//什么意思我也不懂 qwq

大概意思应该是n的所有因数的欧拉函数和为n

分解质因数求欧拉函数

int phi(int n){
	int ans=n;
	for(int i=2;i*i<=n;i++){
		if(n%i==0){
			ans=ans/i*(i-1);
			while(n%i==0) n/=i;
		}
	}
	if(n>1) ans=ans/n*(n-1);
	return ans;
}

线性筛求质因数

/*
特性 :
1.若a为质数,phi[a]=a-1;
2.若a为质数,b mod a=0,phi[a*b]=phi[b]*a
3.若a,b互质,phi[a*b]=phi[a]*phi[b](当a为质数时,if b mod a!=0 ,phi[a*b]=phi[a]*phi[b])
*/
bool vis[maxn+5];
int prime[maxn+5],cnt;
int phi[maxn+5];
void Phi() {
	phi[1]=1;
	vis[1]=true;
	for(int i=2; i<=maxn; i++) {
		if(!vis[i]) prime[cnt++]=i,phi[i]=i-1;
		for(int j=0; j<cnt&&prime[j]*i<=maxn; j++) {
			vis[prime[j]*i]=1;
			if(i%prime[j]==0){
				phi[i*prime[j]]=phi[i]*prime[j];
				break;
			}
			phi[i*prime[j]]=phi[i]*(prime[j]-1);
		}
	}
}

POJ2478 Farey Sequence

求n以内的互质数对

欧拉函数求和,板子题

 

POJ3090 Visible Lattice Points

二维坐标站在(0,0)点上,能看到第一象限哪些点

看到的点的x,y都是互质的,考虑x,y轴和对角线

 

POJ2480 Longge's problem

\sum gcd(i,N)

枚举GCD

统计gcd(i,N)=x的个数,发现其个数为\Theta(\frac{N}{x})

因为x为N的因数,gcd(i,N)=x,i应与\frac{N}{x}互质

f(x)=\sum x*\Theta(\frac{N}{x})

欧拉函数是非完全积性函数,积性函数的约数和也是积性函数

f(N)=f(p_{1}^{a_{1}})*f(p_{2}^{a_{2}})*\cdots *f(p_{n}^{a_{n}})

f(p^n)=\Theta(p^n)+p*\Theta(p^{n-1})+p^2*\Theta(p^{n-2})+\cdots+p^n*\Theta(1)

若a为质数,b mod a=0,phi[a*b]=phi[b]*a

f(p^n)=(p-1)*p^{n-1}+p*(p-1)*p^{n-2}+\cdots+p^n

f(p^n)=n*(p-1)*p^{n-1}+p^n

BZOJ 4804 欧拉心算   心酸

\sum_{i=1}^{n}\sum_{j=1}^{n}\Theta(gcd(i,j))

统计gcd(i,j)=x的个数,为\sum_{i=1}^{n/x}\sum_{j=1}^{n/x}gcd(i,j)=1

即若gcd(i,j)==x,则\frac{i}{x}\frac{j}{x}互质

\sum_{i=1}^{n/x}\sum_{j=1}^{n/x}gcd(i,j)=1与上文中的Visible Lattice Points很像,即为二维坐标上互质的点,2*\sum_{i=1}^{n/x}{\Theta(i)} -1

综上,结论为\sum_{x=1}^{n}\Theta(x)*(2*(\sum_{i=1}^{n/x}\Theta(i))-1),在来一波等值分块就能过了

 

HDU5780 gcd

\sum_{a=1}^{n}\sum_{b=1}^{n}gcd(x^a-1,x^b-1)

先套一波上面的公式\sum_{a=1}^{n}\sum_{b=1}^{n}x^{gcd(a,b)}-1

同上题,取gcd(i,j)=x

\sum_{x=1}^{n}(x^k-1)*(2*(\sum_{i=1}^{n/k}\Theta(i))-1)并等值分块

 

HDU4676 Sum Of Gcd

求L和R,\sum_{i=l}^{r}\sum_{i=j+1}^{r}gcd(a[i],a[j])

一道RMQ问题,明显树状数组和线段树什么的无法维护,但可以用莫队做

那么我们只需要考虑莫队的转移就好

若d1----dn为n的所有因数,\Theta(d_{1})+\Theta(d_{2})+\cdots+\Theta(d_{n})=n

设d1----dn为gcd(a[i],a[j])的因数\Theta(d_{1})+\Theta(d_{2})+\cdots+\Theta(d_{n})=gcd(a[i],a[j])

比如2,4,有cnt[1]=2,cnt[2]=2,cnt[4]=1,因为约数1,2出现两次,1、2为公约数,phi[1]+phi[2]=2=gcd(2,4)

若已知cnt[d]=x,x中任选2个,可以成为gcd(a[i],a[j])的公约数

所以我们统计约数个数就能计算出a[j]与a[1]----a[j-1]的gcd之和

 

同余

a \mod m=b \mod m,则称a,b模m同余 

 

同余类

\mod m相同的数归入一个集合,称为同余类

 

剩余系

m 的 m 个同余类称为完全剩余系

所有与 m 互质的同余类称为简化剩余系

简化剩余系乘法封闭,若 a,b 分别和 m 互质,则 a*b 也 和 m 互质

POJ2773 Happy 2006

求与n互质的第k小的数字 

gcd(n,m)=1->gcd(n+m,m)=1

同理,gcd(n,m)\neq 1->gcd(n+m,m)\neq1

如题,若gcd(3,2006)=1->gcd(3+2006,2006)=1

以n为周期,求余,暴力第k小

欧拉定理

若正整数 a,n 互质,有 a^{\Theta(n)}\equiv 1 \mod n

 

欧拉定理推论

若正整数a,p互质,则对于正整数b
a^b\mod p=a^{b \mod \Theta (p)}\mod p
当正整数 a,p 不一定互质时
a^b \mod p=a^{b \mod \Theta(p)+\Theta(p)}\mod p

 

UVA106992 Huge Mods

a_{1}^{a_{2}^{a_{3}^{\cdots^{a_{n}}}} \mod m

欧拉降幂板子题

 

 

HDU2837 Calculation

f(n)=(n \mod 10)^{f(n/10)}

同上题

 

裴蜀定理

对于任意正整数a,b,存在一对整数x,y满足ax+by=gcd(a,b)

 

扩展欧几里得算法

证明裴蜀定理的过程求出了 x 和 y,这个计算方法称为扩展欧几里得算法

代码求出了 gcd(a,b),并得到了 ax+by=gcd(a,b) 的一组特 解,x 和 y 需要以引用方式传入

//ax1+ by1= gcd(a,b);
//bx2 + (a mod b)y2 = gcd(b, a mod b);
//ax1 + by1 = bx2 + (a - [a / b] * b)y2 = ay2 + bx2 - [a / b] * by2;
//x1 = y2; y1 = x2 - [a / b] * y2;
LL gcd(LL a, LL b, LL &x, LL & y)
{
	if (b == 0) {
		x = 1, y = 0;
		return a;
	}
	int q = gcd(b, a%b, y, x);
	y -= a / b * x;
	return q;
}

POJ2115 Looooops

求以下程序段的循环次数,其中变量为 k 位无符号整数 

for (variable = A; variable != B; variable += C)

a+x*c=b \mod 2^k

x*c+y*2^k=b-a

d=gcd(c,2^k)

特解:ans=x*(b-a)/d

\mod 2^k

最小解:ans=ans \mod (2^k/d)注意负数

 

POJ1061 青蛙的约会

简直和上一题一模一样

 

同余不等式

POJ3530 A Modular Arithmetic Challenge

求x使得L\leqslant D*x\mod M\leqslant R

L\leqslant D*x-M*y\leqslant R

y=0->L\leqslant D*x\leqslant R

y\neq 0->D*x-R\leqslant M*y\leqslant D*x-L

y越小-->x越小

两边求余(-R)\mod D \leqslant (M\mod D)*y\mod D \leqslant (-L)\mod D

 

线性同余方程组

中国剩余定理

m_{1},m_{2},\cdots,m_{n}两两互质,M=m_{1}*m_{2}*m_{3}*\cdots*m_{n},M_{i}=M/m_{i}

t_{i}是线性同余方程M_{i}*t_{i}\equiv 1 \mod m_{i}的一个解

对于任意n个整数a_{1},a_{2},a_{3},\cdots,a_{n},方程组

    x\equiv a_{1}\mod m_{1}

    x\equiv a_{2}\mod m_{2}

    \cdots\cdots

    x\equiv a_{n}\mod m_{n}

Ans=\sum_{i=1}^{n}a_{i}*M_{i}*t_{i}

for (int i = 1; i <= n; i++) {
		M[i] = M / m[i];
		d = gcd(m[i], M[i], x, y);
		ans += y * m[i] * M[i];
	}

 

非互质线性同余方程组

以1、2两式为例

  1. x \equiv a_{1} \mod m_{1}->x=k_{1}*m_{1}+a_{1}
  2. x\equiv a_{2} \mod m_{2}->x=k_{2}*m_{2}+a_{2}

k_{1}*m_{1}+a_{1}=k_{2}*m_{2}+a_{2}->k_{1}*m_{1}=k_{2}*m_{2}+(a_{2}-a_{1})两边求余m_{2}

k_{1}*m_{1}=(r_{2}-r_{1}) \mod m_{2},扩展欧几里得求解k_{1}

k_{1}带会 1 式

x_{1}=k_{1}*m_{1}+a_{1}x_{1}满足1,2两式

x\equiv x_{1}\mod lcm(a_{1},a_{2})

LL CRT() {
	LL m1, m2, a1, a2, x, y, c;
	m1 = m[1]; a1 = a[1];
	bool flag = true;
	for (int i = 2; i <= k; i++) {
		m2 = m[i]; a2 = a[i];
		c = exgcd(m1, m2, x, y);
		if ((a2 - a1) % c)
			flag = false;
		x = (a2 - a1) / c * x;
		y = m2 / c;
		x = (x % y + y) % y;
		a1 = x * m1 + a1;
		m1 = (m1 * m2) / c;
	}
	c = exgcd(1, m1, x, y);
	if (a1 % c) flag = false;
	if (!flag)
		return -1;
	x = a1 / c * x;
	y = m1 / c;
	x = (x % y + y) % y;
	return x;
}

 

POJ2891 Strange Way to Express Integers

板子题

 

GCD Table

题解链接

 

高次同余方程

给定整数a,b,p,求一个非负整数x,使得a^x\equiv b \mod p

 

BSGS算法

x=i*t-j,其中t是步长,这里取t=\sqrt{p},

方程变为a^{i*t-j}\equiv b*a^j \mod p

a^{i*t}\equiv b*a^j \mod p

b*a^j \mod p​​​存​​​​入哈希表,枚举i,计算a^{i*t}是否存在于哈希表中,即可更新答案

此处链接一位大神的博客

int bsgs(int a, int b, int p) {
	map<int, int> H;
	H.clear();
	b %= p;
	int t = (int)sqrt(p) + 1;
	for (int i = 0; i < t; i++) {
		int val = (LL)b * quickpow(a, i, p) % p;
		H[val] = i;
	}
	a = quickpow(a, t, p);
	if (!a) return b ? -1 : 1;
	for (int i = 0; i <= t; i++) {
		int val = quickpow(a, i, p);
		int j = H.find(val) == H.end() ? -1 : H[val];
		if (j >= 0 && i * t >= j) return i * t - j;
	}
	return -1;
}

bzoj2242  [SDOI2011]计算器

板子题

 

原根与指标

知识点链接

 

例题代码

Prime Distance 代码

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
using namespace std;
const unsigned int max = 1 << 31;
const unsigned int maxn = 50000;
void io() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);
}
bool vis[maxn + 5];
unsigned int prime[maxn + 5], cnt = 0;
void Init() {        //预处理<=R的素数
	vis[1] = true;
	for (int i = 2; i <= maxn; i++) {
		if (!vis[i]) prime[cnt++] = i;
		for (int j = 0; j < cnt && prime[j] * i <= maxn; j++) {
			vis[prime[j] * i] = true;
			if (i % prime[j] == 0)break;
		}
	}
}
const unsigned int maxm = 1000000;
bool v[maxm + 10];
void interval_sieve(unsigned int l, unsigned int r) {    //区间筛
	unsigned int limit = sqrt(r * 1.0) + 1;
	if (l == 1)v[0] = true;
	for (int i = 0; i < cnt; i++) {
		if (prime[i] > limit) break;
		for (int j = (l - 1) / prime[i] + 1; j <= r / prime[i]; j++) {
			if (j > 1) v[prime[i] * j - l] = true;
		}
	}
}
int main() {
	Init();
	unsigned int l, r;
	while (cin >> l >> r) {
		interval_sieve(l, r);
		unsigned int p = 0, a = 0, b = 0, c = 0, d = 0, min = r - l + 1, max = 0;
		while (v[p])p++;
		bool flag = false;
		for (unsigned int i = p + 1; i <= r - l; i++) {
			if (!v[i]) {
				flag = true;
				if (i - p < min)
					a = p, b = i, min = i - p;
				if (i - p > max)
					c = p, d = i, max = i - p;
				p = i;
			}
		}
		if (!flag)printf("There are no adjacent primes.\n");
		else printf("%d,%d are closest, %d,%d are most distant.\n", a + l, b + l, c + l, d + l);
		fill(v, v + r - l + 10, 0);
	}
}

Counting Divisors代码

#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
typedef long long LL;
inline void io() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);
}
const LL mod = 998244353;
const int maxn = 1000010;
bool vis[maxn + 5];
int prime[maxn + 5], cnt = 0;
void Prime() {
	vis[1] = true;
	for (int i = 2; i <= maxn; i++) {
		if (!vis[i])prime[cnt++] = i;
		for (int j = 0; j < cnt && prime[j] * i <= maxn; j++) {
			vis[prime[j] * i] = true;
			if (prime[j] % i == 0)break;
		}
	}
}
LL k, num[maxn], d[maxn];
void slove(LL l, LL r) {
	LL limit, g;
	limit = sqrt(r * 1.0) + 1;
	for (int i = 0; i < cnt; i++) {
		if (prime[i] > limit)break;
		LL s = (l + prime[i] - 1) / prime[i] * prime[i];
		for (LL j = s; j <= r; j += prime[i]) {    //用类似筛法的方法压缩时间
			if (num[j - l] % prime[i] == 0) {
				g = 0;
				while (num[j - l] % prime[i] == 0) {
					num[j - l] /= prime[i];
					g++;
				}
				d[j - l] = d[j - l] * (k * g + 1) % mod;
			}
		}
	}
}
int main() {
	io(); Prime();
	int t;cin >> t;
	while (t--){
		LL l, r;
		cin >> l >> r >> k;
		for (int i = 0; i <= r - l; i++)
			num[i] = i + l, d[i] = 1;
		slove(l, r);
		LL ans = 0;
		for (int i = 0; i <= r - l; i++) {
			if (num[i] > 1) {
				d[i] = d[i] * (k + 1) % mod;
			}
			ans += d[i]; ans %= mod;
		}
		cout << ans << '\n';
	}
}

 

Combinations代码

#include <iostream>
#include <cstdio>
using namespace std;
const int maxn = 50005;
void io() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);
}
bool vis[maxn + 5];
int prime[maxn + 5], cnt;
void Prime() {
	prime[1] = true;
	for (int i = 2; i <= maxn; i++) {
		if (!vis[i])prime[cnt++] = i;
		for (int j = 0; j < cnt && prime[j] * i <= maxn; j++) {
			vis[prime[j] * i] = true;
			if (prime[j] % i == 0)break;
		}
	}
}
int GetNum(int N, int x) {
	int res = 0, m = x;
	while (N >= m) {
		res += N / m;
		m *= x;
	}
	return res;
}
int main() {
	io(); Prime();
	int n, m;
	while (cin >> n >> m) {
		int k = n - m, ans = 0, limit = n;
		for (int i = 0; i < cnt; i++) {
			if (prime[i] > limit)break;
			if (GetNum(n, prime[i]) - GetNum(k, prime[i]) - GetNum(m, prime[i]) > 0)
				ans++;
		}
		printf("%d\n", ans);
	}
}

余数之和代码

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long LL;
void io() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
}
// k mod i= k - k / i * i
int main() {
	io();
	LL ans, n, k, r;
	cin >> n >> k;
	ans = n * k;
	n = min(n, k);
	for (LL l = 1; l <= n; l = r + 1) {
		LL u = k / l;
		r = min(k / u, n);
		ans -= (l + r) * (r - l + 1) / 2 * u;
	}
	cout << ans << '\n';
}

模积和代码

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long LL;
void io() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
}
LL mod = 19940417;
LL inv[8];    //求逆元
void init() {
	inv[1] = 1;
	for (LL i = 2; i <= 6; i++) {
		inv[i] = (mod - mod / i) * (LL)1 * inv[mod % i] % mod;
	}
}
// k mod i= k - k / i * i
LL GetNum(LL n) {        //区间分块
	LL ans = n * n % mod, r;
	for (LL l = 1; l <= n; l = r + 1) {
		LL u = n / l;
		r = min(n / u, n);
		ans = ans - (l + r) * (r - l + 1)/2 % mod * u % mod;
	}
	return ans % mod;
}
//sum(i,min(n,m))=(n*m-m*n/i*i-n*m/i*i+n/i*i*m/i*i)
int main() {
	io(); init();
	LL n, m, res;
	cin >> n >> m;
	res = GetNum(n) * GetNum(m) % mod;
	if (n > m)swap(n, m); 
	LL cnt = n * m % mod * n % mod;
	for (LL l = 1, r; l <= n; l = r + 1) {
		r = min(n / (n / l), m / (m / l));     //选择较小的块移动
		cnt += (n / l) * (m / l) % mod * ((r * (r + 1) % mod * (2 * r + 1) % mod * inv[6] % mod) - ((l - 1) * l % mod * (2 * l - 1) % mod * inv[6] % mod) + mod) % mod;
		cnt -= m / l * n % mod * ((l + r) * (r - l + 1)/2 % mod); if (cnt < 0)cnt += mod;
		cnt -= n / l * m % mod * ((l + r) * (r - l + 1)/2 % mod); if (cnt < 0)cnt += mod;
	}
	res -= cnt; res %= mod; if (res < 0)res+=mod;
	cout << res << '\n';
}

斐波那契公约数代码

#include <iostream>
#include <cstdio>
using namespace std;
#pragma warning (disable:4996)
typedef long long int LL;
const LL mod = 1e8;
LL res[3][3] = { 0,0,0,0,1,1 }, r[3][3] = { 0,0,0,0,0,1,0,1,1 }, t[3][3];
LL gcd(LL a, LL b)
{
	LL c;
	while (c = a % b)
	{
		a = b;
		b = c;
	}
	return b;
}
void mul(LL res[3][3], LL m[3][3], LL h)
{
	for (int i = 1; i <= h; i++)
		for (int j = 1; j <= 2; j++)
			t[i][j] = (res[i][1] * m[1][j] % mod + res[i][2] * m[2][j] % mod) % mod;
	for (int i = 1; i <= h; i++)
		for (int j = 1; j <= 2; j++)
			res[i][j] = t[i][j];
}
void quickmul(LL p)
{
	while (p)
	{
		if (p & 1)
			mul(res, r, 1);
		mul(r, r, 2);
		p >>= 1;
	}
}
int main()
{
	LL n, m;
	scanf("%lld%lld", &n, &m);
	LL cnt = gcd(n, m);
	if (cnt == 1 || cnt == 2)
		printf("1\n");
	else
	{
		quickmul(gcd(n, m) - 2);
		printf("%lld\n", res[1][2]);
	}
}

GCD代码 

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <map>
#include <vector>
using namespace std;
typedef pair<int, int> pii;
typedef long long LL;
const int maxn = 100005;
map<int, LL> Map;
vector<pii> E[maxn];
int gcd(int a, int b) {
	int c;
	while (c=a%b){
		a = b;
		b = c;
	}
	return b;
}
int a[maxn], l[maxn], v[maxn];
int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t, g = 0, n, q; cin >> t;
	while (t--){
		cout << "Case #" << ++g << ":\n";
		cin >> n;
		for (int i = 1; i <= n; i++)cin >> a[i];
		int j;
		for (int i = 1; i <= n; i++) {
			for (v[i] = a[i], j = l[i] = i; j; j = l[j] - 1) {
				v[j] = gcd(v[j], a[i]);
				while (l[j] > 1 && gcd(a[i], v[l[j] - 1]) == gcd(a[i], v[j]))
					l[j] = l[l[j] - 1];
				E[i].push_back(pii(l[j], v[j]));
				Map[v[j]] += LL(j - l[j] + 1);
			}
		}
		cin >> q;
		int L, R;
		for (int i = 1; i <= q; i++) {
			cin >> L >> R;
			//cout << r << '\n';
			for (int j = 0; j < E[R].size(); j++) {
				if (L >= E[R][j].first) {
					cout << E[R][j].second << ' ' << Map[E[R][j].second] << '\n';
					break;
				}
			}
		}
		for (int i = 0; i <= n; i++) {
			E[i].clear(); 
			l[i] = v[i] = 0; 
		}
		Map.clear();
	}
}

Different GCD Subarray Query代码

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <map>
using namespace std;
const int maxn=100005;
int gcd(int a,int b) {
	return b==0?a:gcd(b,a%b);
}
int n,q;
int tree[maxn];
inline int lowbit(int x) {
	return x & -x;
}
void update(int x, int value) {
	while (x <= n) {
		tree[x] += value;
		x += lowbit(x);
	}
}
int query(int x) {
	int ans = 0;
	while (x) {
		ans += tree[x];
		x -= lowbit(x);
	}
	return ans;
}
int a[maxn],l[maxn],v[maxn];
map<int,int> Map;
void modify(int i) {
	int j;
	for (v[i] = a[i], j = l[i] = i; j; j = l[j] - 1) {
		v[j] = gcd(v[j], a[i]);
		while (l[j] > 1 && gcd(a[i], v[l[j] - 1]) == gcd(a[i], v[j]))
			l[j] = l[l[j] - 1];
		int p=Map[v[j]];
		if(p==0) {
			update(j,1);
		} else if(p!=j) {
			update(p,-1);
			update(j,1);
		}
		Map[v[j]]=j;
	}
}
struct node {
	int left;
	int right;
	int ops;
	friend bool operator <(node &a,node &b) {
		return a.right<b.right;
	}
} line[maxn];
int res[maxn];
int main() {
	while(cin>>n>>q) {
		for(int i=1; i<=n; i++)cin>>a[i];
		for(int i=1; i<=q; i++) {
			cin>>line[i].left>>line[i].right;
			line[i].ops=i;
		}
		sort(line+1,line+1+q);
		int next=1;
		for(int i=1; i<=q; i++) {
			while(next<=line[i].right) {
				modify(next);
				next++;
			}
			res[line[i].ops]=query(line[i].right)-query(line[i].left-1);
		}
		for(int i=1; i<=q; i++)
			cout<<res[i]<<'\n';
		fill(l,l+n+1,0);
		fill(v,v+n+1,0);
		fill(tree,tree+n+1,0);
		Map.clear();
	}
}

Farey Sequence代码

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long LL;
const int maxn = 1000005;
bool vis[maxn + 5];
int prime[maxn + 5], cnt;
int phi[maxn + 5];
void Phi() {
	phi[1] = 1;
	vis[1] = true;
	for (int i = 2; i <= maxn; i++) {
		if (!vis[i]) prime[cnt++] = i, phi[i] = i - 1;
		for (int j = 0; j < cnt && prime[j] * i <= maxn; j++) {
			vis[prime[j] * i] = 1;
			if (i % prime[j] == 0) {
				phi[i * prime[j]] = phi[i] * prime[j];
				break;
			}
			phi[i * prime[j]] = phi[i] * (prime[j] - 1);
		}
	}
}
LL sum[maxn+5];
int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	Phi(); phi[1] = 0;
	for (int i = 1; i <= maxn; i++)
		sum[i] = sum[i - 1] + phi[i];
	int n;
	while (cin>>n&&n)
		cout << sum[n] << '\n';
}

Visible Lattice Points代码

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long LL;
const int maxn = 1005;
bool vis[maxn + 5];
int prime[maxn + 5], cnt;
int phi[maxn + 5];
void Phi() {
	phi[1] = 1;
	vis[1] = true;
	for (int i = 2; i <= maxn; i++) {
		if (!vis[i]) prime[cnt++] = i, phi[i] = i - 1;
		for (int j = 0; j < cnt && prime[j] * i <= maxn; j++) {
			vis[prime[j] * i] = 1;
			if (i % prime[j] == 0) {
				phi[i * prime[j]] = phi[i] * prime[j];
				break;
			}
			phi[i * prime[j]] = phi[i] * (prime[j] - 1);
		}
	}
}
int sum[maxn + 5];
int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	Phi(); phi[1] = 0;
	for (int i = 1; i <= maxn; i++)
		sum[i] = sum[i - 1] + phi[i];
	int n, x, g = 0; cin >> n;
	while (n--) {
		cin >> x;
		cout << ++g << ' ' << x << ' ' << 2 * sum[x] + 3<<endl;
	}
}

Longge's problem代码

//推导见数论博客
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long LL;
const int maxn = 47000;
bool vis[maxn + 5];
int prime[maxn + 5], cnt = 0;
void Prime() {
	vis[1] = true;
	for (int i = 2; i <= maxn; i++) {
		if (!vis[i]) prime[cnt++] = i;
		for (int j = 0; j < cnt && i * prime[j] <= maxn; j++) {
			vis[prime[j] * i] = true;
			if (i % prime[j] == 0)break;
		}
	}
}
void slove(int n) {
	int limit = sqrt(n * 1.0) + 1;
	LL ans = 1;
	int m, g;
	for (int i = 0; i < cnt; i++) {
		if (prime[i] > limit) break;
		if (n % prime[i] == 0) {
			m = n; g = 0;
			while (n % prime[i] == 0) {
				n /= prime[i];
				g++;
			}
			ans = ans * (LL(m) / n / prime[i] * g * (prime[i] - 1) + m / n);
		}
	}
	if (n > 1) ans = ans * (LL(2) * n - 1);
	cout << ans << '\n';
}
int main() {
	Prime();
	int n;
	while (cin >> n)
		slove(n);
}

欧拉心算  代码

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long LL;
const int maxn = 10000005;
bool vis[maxn + 5];
int prime[maxn + 5], cnt;
int phi[maxn + 5];
LL sum[maxn + 5];
void Phi() {
	phi[1] = 1;
	vis[1] = true;
	for (int i = 2; i <= maxn; i++) {
		if (!vis[i]) prime[cnt++] = i, phi[i] = i - 1;
		for (int j = 0; j < cnt && prime[j] * i <= maxn; j++) {
			vis[prime[j] * i] = 1;
			if (i % prime[j] == 0) {
				phi[i * prime[j]] = phi[i] * prime[j];
				break;
			}
			phi[i * prime[j]] = phi[i] * (prime[j] - 1);
		}
	}
	for (int i = 1; i <= maxn; i++)
		sum[i] = sum[i - 1] + phi[i];
}
//Sum(phi[x])*2*Sum(phi[n/x])-1)
void slove(int n) {
	LL ans = 0;
	for (int l = 1, r; l <= n; l = r + 1) {
		int u = n / l;
		r = n / u;
		ans += (sum[r] - sum[l - 1]) * (sum[u] * 2 - 1);
	}
	cout << ans << '\n';
}
int main() {
	Phi(); 
	int t, n;
	cin >> t;
	while (t--){
		cin >> n;
		slove(n);
	}
}

gcd代码

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long LL;
const int maxn = 1000005;
const LL mod = 1e9 + 7;
bool vis[maxn + 5];
int prime[maxn + 5], cnt;
int phi[maxn + 5];
LL sum[maxn + 5];
void Phi() {
	phi[1] = 1;
	vis[1] = true;
	for (int i = 2; i <= maxn; i++) {
		if (!vis[i]) prime[cnt++] = i, phi[i] = i - 1;
		for (int j = 0; j < cnt && prime[j] * i <= maxn; j++) {
			vis[prime[j] * i] = 1;
			if (i % prime[j] == 0) {
				phi[i * prime[j]] = phi[i] * prime[j];
				break;
			}
			phi[i * prime[j]] = phi[i] * (prime[j] - 1);
		}
	}
	for (int i = 1; i <= maxn; i++) {
		sum[i] = sum[i - 1] + phi[i];
		sum[i] %= mod;
	}
}
LL quickpow(LL x,LL k) {
	LL res = 1, m = x;
	while(k){
		if (k & 1) res *= m, res %= mod;
		m *= m; m %= mod;
		k >>= 1;
	}
	return res;
}
LL GetSum(LL x, LL l, LL r) {
	LL inv = quickpow(x - 1, mod - 2);
	LL ans = quickpow(x, l) * ((quickpow(x, r - l + 1) - 1 + mod) % mod) % mod * inv % mod;
	ans = ans - (r - l + 1) + mod; ans %= mod;
	return ans;
}
//Sum(x^k-1)*2*Sum(phi[n/x])-1)
void slove(LL x, LL n) {
	LL ans = 0;
	for (LL l = 1, r; l <= n; l = r + 1) {
		LL u = n / l;
		r = n / u;
		ans += GetSum(x, l, r) * ((sum[u] * 2 - 1) % mod) % mod;
		ans %= mod;
	}
	cout << ans << '\n';
}
int main() {
	Phi();
	int t, n, x;
	cin >> t;
	while (t--) {
		cin >> x >> n;
		if (x == 1) {
			cout << "0\n";
			continue;
		}
		slove(x, n);
	}
}

Sum Of Gcd代码

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#include <cmath>
using namespace std;
#pragma warning (disable:4996)
typedef long long LL;
const int maxn = 20005;
int E[maxn + 5][233];
void Init() {
	int cnt;
	for (int i = 1; i < maxn; i++) {
		cnt = 0;
		for (int j = 1; j * j <= i; j++) {
			if (i % j == 0) {
				E[i][++cnt] = j;
				if (j * j != i)
					E[i][++cnt] = i / j;
			}
		}
		E[i][0] = cnt;
	}
}
bool vis[maxn + 5];
int prime[maxn + 5], cnt;
int phi[maxn + 5];
void Phi() {
	phi[1] = 1;
	vis[1] = true;
	for (int i = 2; i <= maxn; i++) {
		if (!vis[i]) prime[cnt++] = i, phi[i] = i - 1;
		for (int j = 0; j < cnt && prime[j] * i <= maxn; j++) {
			vis[prime[j] * i] = 1;
			if (i % prime[j] == 0) {
				phi[i * prime[j]] = phi[i] * prime[j];
				break;
			}
			phi[i * prime[j]] = phi[i] * (prime[j] - 1);
		}
	}
}
int a[maxn], ops[maxn];
LL res[maxn];
struct Node {
	int id;
	int left;
	int right;
	bool operator <(const Node& a)const{
		if (ops[left] == ops[a.left])
			return right < a.right;
		return ops[left] < ops[a.left];
	}
} q[maxn];
LL num[maxn];
int main() {
	Init();
	Phi();
	int t, n, m, g = 0;
	cin >> t;
	while (t--) {
		printf("Case #%d:\n", ++g);
		scanf("%d", &n);
		int Size = (int)sqrt(n * 1.0);
		for (int i = 1; i <= n; i++)scanf("%d", &a[i]);
		for (int i = 1; i <= n; i++)ops[i] = i / Size;
		scanf("%d", &m);
		for (int i = 1; i <= m; i++){
			scanf("%d%d", &q[i].left, &q[i].right);
			q[i].id = i;
		}
		sort(q + 1, q + 1 + m);
		int stdl = 1, stdr = 0;
		LL ans = 0; int d;
		for (int i = 1; i <= m; i++){
			while (stdl > q[i].left){
				stdl--;
				for (int j = 1; j <= E[a[stdl]][0]; j++) {
					d = E[a[stdl]][j];
					num[d]++;
					ans += (num[d] - 1) * phi[d];
				}
			}
			while (stdr < q[i].right){
				stdr++;
				for (int j = 1; j <= E[a[stdr]][0]; j++) {
					d = E[a[stdr]][j];
					num[d]++;
					ans += (num[d] - 1) * phi[d];
				}
			}
			while (stdl < q[i].left){
				for (int j = 1; j <= E[a[stdl]][0]; j++) {
					d = E[a[stdl]][j];
					ans -= (num[d] - 1) * phi[d];
					num[d]--;
				}
				stdl++;
			}
			while (stdr > q[i].right){
				for (int j = 1; j <= E[a[stdr]][0]; j++) {
					d = E[a[stdr]][j];
					ans -= (num[d] - 1) * phi[d];
					num[d]--;
				}
				stdr--;
			}
			res[q[i].id] = ans;
		}
		for (int i = 1; i <= m; i++)
			printf("%lld\n", res[i]);
		memset(num, 0, sizeof(num));
	}
}

Happy 2006代码

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
#pragma warning (disable:4996)
typedef long long LL;
int Phi(int n) {
	int ans = n;
	for (int i = 2; i * i <= n; i++) {
		if (n % i == 0) {
			ans = ans / i * (i - 1);
			while (n % i == 0) n /= i;
		}
	}
	if (n > 1) ans = ans / n * (n - 1);
	return ans;
}
int gcd(int a, int b) {
	return b == 0 ? a : gcd(b, a % b);
}
int main() {
	int n, k, phi;
	while (~scanf("%d%d", &n, &k)) {
		phi = Phi(n);
		LL ans = LL(k - 1) / phi * n;
		k %= phi;
		if (k == 0)k = phi;
		for (int i = 1; i <= n; i++) {
			if (gcd(i, n) == 1)
				k--;
			if (k == 0) {
				ans += LL(i); 
				break;
			}
		}
		printf("%lld\n", ans);
	}
}

Huge Mods代码

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
#pragma warning (disable:4996)
typedef long long int LL;
int Phi(int n) {
	int ans = n;
	for (int i = 2; i * i <= n; i++) {
		if (n % i == 0) {
			ans = ans / i * (i - 1);
			while (n % i == 0) n /= i;
		}
	}
	if (n > 1) ans = ans / n * (n - 1);
	return ans;
}
int mod, k;
int a[30];
int quickpow(LL m, LL p, LL mod) {
	LL res = 1, f1 = 0, f2 = 0;
	while (p) {
		if (p & 1) {
			f1 |= (res * m >= mod || f2);
			res *= m; res %= mod;
		}
		f2 |= (m * m >= mod);
		m *= m; m %= mod;
		p >>= 1;
	}
	return res + f1 * mod;
}
int slove(int x, int mod) {
	if (x == k) return quickpow(a[x], 1, mod);
	return quickpow(a[x], slove(x + 1, Phi(mod)), mod);
}
int main() {
	int g = 0;
	while (cin >> mod) {
		if (mod == '#')break;
		cin >> k;
		for (int i = 1; i <= k; i++) cin >> a[i];
		printf("Case #%d: %d\n", ++g, slove(1, mod) % mod);
	}
}

Calculation代码

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
#pragma warning (disable:4996)
typedef long long int LL;
LL Phi(LL n) {
	LL ans = n;
	for (int i = 2; i * i <= n; i++) {
		if (n % i == 0) {
			ans = ans / i * (i - 1);
			while (n % i == 0) n /= i;
		}
	}
	if (n > 1) ans = ans / n * (n - 1);
	return ans;
}
LL quickpow(LL m, LL p, LL mod) {
	LL res = 1, f1 = 0, f2 = 0;
	while (p) {
		if (p & 1) {
			f1 |= (res * m >= mod || f2);
			res *= m; res %= mod;
		}
		f2 |= (m * m >= mod);
		m *= m; m %= mod;
		p >>= 1;
	}
	return res + f1 * mod;
}
LL n, m;
//f(n) = (n % 10) ^ f(n / 10)
LL slove(LL x, LL mod) {
	if (x == 0) return 1;
	return quickpow(x % 10, slove(x / 10, Phi(mod)), mod);
}
int main() {
	int t;
	scanf("%d", &t);
	while (t--) {
		scanf("%lld%lld", &n, &m);
		printf("%lld\n", slove(n, m) % m);
	}
}

Looooops代码

#include <iostream>
#include <cstdio>
using namespace std;
#pragma warning (disable:4996)
typedef long long LL;
LL in2[35];
void Init() {
	for (int i = 1; i <= 34; i++)
		in2[i] = LL(1) << i;
}
LL gcd(LL a, LL b, LL& x, LL& y)
{
	if (b == 0) {
		x = 1, y = 0;
		return a;
	}
	int q = gcd(b, a % b, y, x);
	y -= a / b * x;
	return q;
}
int main() {
	Init();
	LL a, b, c, k;
	while (cin >> a >> b >> c >> k && a + b + c + k) {
		LL x, y;
		LL d = gcd(c, in2[k], x, y);
		if ((b - a) % d == 0) {
			LL ans = x * (b - a) / d % in2[k];
			printf("%lld\n", (ans % (in2[k] / d) + in2[k] / d) % (in2[k] / d));
		}
		else
			printf("FOREVER\n");
	}
}

青蛙的约会代码

#include <iostream>
#include <cstdio>
using namespace std;
#pragma warning (disable:4996)
typedef long long LL;
LL in2[35];
void Init() {
	for (int i = 1; i <= 34; i++)
		in2[i] = LL(1) << i;
}
LL gcd(LL a, LL b, LL& x, LL& y)
{
	if (b == 0) {
		x = 1, y = 0;
		return a;
	}
	int q = gcd(b, a % b, y, x);
	y -= a / b * x;
	return q;
}
int main() {
	LL a, b, m, n, L, x, y;
	cin >> a >> b >> m >> n >> L;
	LL c = a - b; 
	a = n - m;
	LL d = gcd(a, L, x, y);
	if (c % d == 0) {
		LL ans = x * c / d;
		ans %= (L / d);
		if (ans < 0)ans += L / d;
		printf("%lld\n", ans);
	}
	else
		printf("Impossible\n");
}

A Modular Arithmetic Challenge代码

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
#pragma warning (disable:4996)
typedef long long LL;
LL slove(LL M, LL D, LL L, LL R) {
	if (L > R || D == 0) return -1;
	if (R / D * D >= L) return (L + D - 1) / D;
	LL l = (-L) % D; if (l < 0) l += D;
	LL r = (-R) % D; if (r < 0) r += D;
	LL x = slove(D, M % D, r, l);
	if (x == -1)return -1;
	return (L + x * M + D - 1) / D;
}
int main() {
	LL D, M, L, R, t;
	cin >> t;
	while (t--) {
		cin >> M >> D >> L >> R;
		R = min(M - 1, R);
		cout << slove(M, D, L, R) << '\n';
	}
}

Strange Way to Express Integers代码

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
#pragma warning (disable:4996)
typedef long long LL;
LL gcd(LL a, LL b, LL& x, LL& y)
{
	if (b == 0) {
		x = 1;
		y = 0;
		return a;
	}
	LL q = gcd(b, a % b, y, x);
	y -= a / b * x;
	return q;
}
int main() {
	LL k, m1, m2, a1, a2, x, y, c;
	while (~scanf("%lld", &k)) {
		scanf("%lld%lld", &m1, &a1);
		bool flag = true;
		k--;
		while (k--) {
			scanf("%lld%lld", &m2, &a2);
			c = gcd(m1, m2, x, y);
			if ((a2 - a1) % c) flag = false;
			if(flag){
				x = (a2 - a1) / c * x;
				y = m2 / c;
				x = (x % y + y) % y;
				a1 = x * m1 + a1;
				m1 = (m1 * m2) / c;
			}
		}
		c = gcd(1, m1, x, y);
		if (a1 % c) flag = false;
		if(!flag) printf("-1\n");
		else {
			x = a1 / c * x;
			y = m1 / c;
			x = (x % y + y) % y;
			printf("%lld\n", x);
		}
	}
}

GCD Table代码

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
#pragma warning (disable:4996)
typedef long long LL;
LL gcd(LL a, LL b) {
	return b == 0 ? a : gcd(b, a % b);
}
LL lcm(LL a, LL b) {
	return a / gcd(a, b) * b;
}
LL exgcd(LL a, LL b, LL& x, LL& y) {
	if (b == 0) {
		x = 1;
		y = 0;
		return a;
	}
	LL q = exgcd(b, a % b, y, x);
	y -= a / b * x;
	return q;
}
LL mul(LL x, LL p, LL mod) {
	if (p < 0) x = -x, p = -p;
	LL ret = 0;
	for (; p; p >>= 1, x = (x + x) % mod) if (p & 1) ret = (ret + x) % mod;
	return ret;
}
LL _x, _y, k;
LL m[10005], a[10005];
LL CRT() {
	LL m1, m2, a1, a2, x, y, c;
	m1 = m[1];
	a1 = a[1];
	bool flag = true;
	for (int i = 2; i <= k; i++) {
		m2 = m[i];
		a2 = a[i];
		c = exgcd(m1, m2, x, y);
		if ((a2 - a1) % c)
			flag = false;
		y = m2 / c;
		x = mul((a2 - a1) / c, x, y);
		x = (x % y + y) % y;
		a1 = x * m1 + a1;
		m1 = (m1 * m2) / c;
	}
	c = exgcd(1, m1, x, y);
	if (a1 % c) flag = false;
	if (!flag)
		return -1;
	x = a1 / c * x;
	y = m1 / c;
	x = (x % y + y) % y;
	return x == 0 ? y : x;
}
int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin >> _x >> _y >> k;
	LL Lcm = 1;
	for (int i = 1; i <= k; i++) {
		cin >> m[i];
		Lcm = lcm(Lcm, m[i]);
		if (Lcm > _x) {
			printf("NO\n");
			return 0;
		}
		a[i] = ((m[i] - i + 1) % m[i] + m[i]) % m[i];
	}
	LL ans = CRT();
	if (ans == -1 || ans + k - 1 > _y) {
		printf("NO\n");
		return 0;
	}
	for (int i = 1; i <= k; i++) {
		if (gcd(Lcm, ans + i - 1) != m[i]) {
			printf("NO\n");
			return 0;
		}
	}
	printf("YES\n");
}

 [SDOI2011]计算器代码

#include <iostream>
#include <cstdio>
#include <map>
#include <cmath>
using namespace std;
#pragma warning (disable:4996)
typedef long long LL;
LL quickpow(LL m, LL p, LL mod) {
	LL res = 1;
	while (p) {
		if (p & 1) {
			res *= m;
			res %= mod;
		}
		m *= m;
		m %= mod;
		p >>= 1;
	}
	return res;
}
LL exgcd(LL a, LL b, LL& x, LL& y)
{
	if (b == 0) {
		x = 1, y = 0;
		return a;
	}
	LL q = exgcd(b, a % b, y, x);
	y -= a / b * x;
	return q;
}
LL bsgs(LL a, LL b, LL p) {
	map<LL, LL> H;
	H.clear();
	b %= p;
	LL t = (LL)sqrt(p) + 1;
	for (int i = 0; i < t; i++) {
		LL val = (LL)b * quickpow(a, i, p) % p;
		H[val] = i;
	}
	a = quickpow(a, t, p);
	if (!a) return b ? -1 : 1;
	for (int i = 0; i <= t; i++) {
		LL val = quickpow(a, i, p);
		LL j = H.find(val) == H.end() ? -1 : H[val];
		if (j >= 0 && i * t >= j) return i * t - j;
	}
	return -1;
}
int main() {
	LL t, k, _y, _z, _p, x, y;
	while (~scanf("%lld%lld", &t, &k)) {
		while (t--) {
			scanf("%lld%lld%lld", &_y, &_z, &_p);
			if (k == 1) {
				printf("%lld\n",quickpow(_y, _z, _p) % _p);
			}
			else if (k == 2) {
				LL a = _y, b = _p, d;
				d = exgcd(a, b, x, y);
				if (_z % d) {
					printf("Orz, I cannot find x!\n");
					continue;
				}
				x = _z / d * x;
				y = _p / d;
				x %= y; if (x < 0)x += y;
				printf("%lld\n", x);
			}
			else {
				LL ans = bsgs(_y, _z, _p);
				if (ans == -1) {
					printf("Orz, I cannot find x!\n");
					continue;
				}
				printf("%lld\n", ans);
			}
		}
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值