简单数学

最大公约数

int gcd(int a, int b) {
	if(b == 0) return a;	//  0 和 a的最大公约数是 a
	else return gcd(b, a % b);
}
// or
int gcd(int a, int b) {
	return !b ? a : gcd(b, a % b);
}

最大公倍数

int lcm(int a, int b) {
	int d = gcd(a, b);
	return a / d * b;
}

分数运算

// 分数表示
struct Fraction {
	int up, down;
};
// 约分
Fraction reduction( Fraction a) {
	if(a.down < 0) {		// 统一分子的符号表示正负
		a.down = -a.down;
		a.up = -a.up;
	}
	if(a.up == 0) {			// 表示0
		a.down = 1;
	}
	else {
		int d = gcd(abs(a.up), abs(a.down));
		a.up /= d;
		a.down /= d;
	}
	return a;
}
// 加法
Fraction add(Fraction a, Fraction b) {
	Fraction res;
	res.up = a.up * b.down + a.down * b.up;
	res.down = a.down * b.down;
	return reduction(res);
}
// 减法
Fraction minus(Fraction a, Fraction b) {
	Fraction res;
	res.up = a.up * b.down - a.down * b.up;
	res.down = a.down * b.down;
	return reduction(res);
}
// 乘法
Fraction multi(Fraction a, Fraction b) {
	Fraction res;
	res.up = a.up * b.up;
	res.down = a.down * b.down;
	return reduction(res);
}
// 除法
Fraction divide(Fraction a, Fraction b) {
	Fraction res;
	res.up = a.up * b.down;
	res.down = a.down * b.up;
	return reduction(res);
}
// 输出
void printFraction(Fraction f) {
	f = reduction(f);
	if(f.down == 1)
		printf("%lld\n", f.up);
	else if(abs(a.up) > a.down) 
		printf("%d %d/%d", a.up/a.down, abs(a.up) % a.down, a.down);
	else
		printf("%d/%d", a.up, a.down);
}

素数
除了1和本身, 不能被其他数整除的一类数

// 判断
bool isPrime(int a) {
	if(a <= 1) return false;
	int sqr = (int)sqrt(1.0*a);	// 代替a 依次除以 2,3...... n-1 O(sqrt(a))
	for(int i = 2; i <= sqr; ++i) {
		if(a % i == 0) return false;
	}
	return true;
}
// 素数打表
#include <cstdio>
#include <cmath>

const int maxn = 110;
int prime[maxn], count = 0;
bool p[maxn] = {0};
void findPrime() {
	for(int i = 1; i < maxn; ++i) {
		if(isPrime(i)) {
			prime[count++] = i;
			p[i] = true;
		}
	}
}
int main() {
	findPrime();
	for(int i = 0; i < count; i++) {
		printf("%d ", prime[i]);
	}
	return 0;
}

// 素数筛选法
const int maxn = 110;
int prime[maxn], count = 0;
bool p[maxn] = {0};	// false 表示是素数
void Eratosthenes() {
	for(int i = 2; i < maxn; i ++) {
		if(p[i] == false) {		// 若是素数
			prime[count++] = i;
			for(int j = i + i; j < maxn; j += i) {
				p[j] = true;	// 剔除掉已知素数的倍数
			}
		}
	}
}

质因子分解
180 = 2^2 * 3^2 * 5^1
质因子分布结论: 2~~一堆~~sqrt(n)~~最多一个~~n

struct factor {
	int x, cnt;	// x表示质因子, cnt表示指数
}fac[10];
if(n == 1) printf("1 = 1");		// 1 单独处理
// 枚举1~sqrt(n)范围内的所有素数,判断是否是n的质因子
for(int i = 0; i < count && prime[i] <= sqr; i++){
	if(n % prime[i] == 0) {	// 如果prime[i]是n的质因子
		fac[num].x = prime[i];
		fac[num].cnt = 0;
		while(n % prime[i] == 0) {
			fac[num].cnt++;
			n /= prime[i];
		}
		num++;
	}
	if(n == 1) break;
}
if(n != 1) {	// 若无法被sqrt(n)以内的质因子除尽
	fac[num].x = n;
	fac[num].cnt = 1;
	num++;
}
// 比如179 = 179^1

大整数运算

// 大整数结构
struct bign {
	int d[1000];
	int len;
	bign() {
		memset(d, 0, sizeof(d));
		len = 0;
	}
};
// 将数字字符串转换成目标结构
bign change(char[] str) {
	bign c;
	c.len = strlen(str);
	for(int i = 0; i < c.len; i++) {
		c.d[i] = str[c.len - 1 - i] - '0';
	} 
	return c;
}
// 大整数比大小
int compare(bign a, bign b) {
	if(a.len > b.len) return 1;
	else if( a.len < b.len) return -1;
	else {
		for(int i = a.len; i >= 0; i--) {
			if(a.d[i] > b.d[i]) return 1;
			else if(a.d[i] < b.d[i]) return -1;
		}
		return 0;
	}
}
// 加法
bign add(bign a, bign b) {
	bign c;
	int carry = 0;
	for(int i = 0; i < a.len || i < b.len; i++) {
		int temp = a.d[i] + b.d[i] + carry;
		c.d[c.len++] = temp % 10;
		carry = temp / 10;
	}
	if(carry != 0) {
		c.d[c.len++] = carry;
	}
	return c;
}
// 减法
bign minus(bign a, bign b) {
	bign c;
	for(int i = 0; i < a.len || i < b.len; i++) {
		if(a.d[i] < b.d[i]) {	// 不够减 借位 
			a.d[i + 1]--;
			a.d[i] += 10;
		}
		c.d[c.len++] = a.d[i] - b.d[i];
	} 
	while(c.len > 1 && c.d[c.len - 1] == 0) {
		c.len--;
	}
	return c;
}
// 乘法
bign multi(bign a, int b) {
	bign c;
	int carry = 0;
	for(int i = 0; i < a.len; i++) {
		int temp = a.d[i] * b + carry;
		c.d[c.len++] = temp % 10;
		carry = temp / 10;
	}
	while(carry != 0) {
		c.d[c.len++] = carry % 10;
		carry /= 10;
	}
	return c;
}
// 除法
bign divide(bign a, int b, int& r) {
	bign c;
	c.len = a.len;
	for(int i = a.len - 1; i > 0; i --) {
		r = r * 10 + a.d[i];
		if(r < b) c.d[i] = 10;
		else {
			c.d[i] = r / b;
			r %= b;
		}
	}
	while(c.len > 1 && c.d[c.len - 1] == 0) {
		c.len--;
	}
}

组合数运算

// 组合数运算 C 上m 下n 
long long C(long long m, long long n) {
	long long ans = 1;
	for(long long i = 1; i <= m; i++) {
		ans = ans * (n - m + i) / i;
	}
	return ans;
} 
// Cmn % p p是素数 设p是全局变量 
int Lucas(int n, int m) {
	if(m == 0) return 1;
	return C(n % p, m % p) * Lucas(n / p, m / p) % p;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值