NOIP前 基础数学模板

标签: NOIP 数学 模板
403人阅读 评论(0) 收藏 举报
分类:
/*
	created by scarlyw
	基础数学模板 
*/
#include <bits/stdc++.h>

//最大公约数 & 最小公倍数 
namespace gcd_lcm() {
//最大公约数 O(logn)
inline int gcd(int a, int b) {
	return b ? gcd(b, a % b) : a;
}

//最小公倍数 (logn)
inline int lcm(int a, int b) {
	return a * b / gcd(a, b);
}
}

//线筛 
namespace s_seive {

//线筛质数 和 莫比乌斯函数(容斥函数) O(n)
int prime[MAXN], miu[MAXN]; 
int prime_cnt, n;
bool not_prime[MAXN];
inline void seive(int n) {
	not_prime[1] = true, miu[1] = 1;
	for (int i = 2; i <= n; ++i) {
		if (!not_prime[i]) prime[++prime_cnt] = i, miu[i] = -1;
		for (int j = 1; j <= prime_cnt && prime[j] * i <= n; ++j) {
			not_prime[i * prime[j]] = true;
			if (i % prime[j] == 0) {
				miu[i * prime[j]] = 0;
				break;
			}
			miu[i * prime[j]] = -miu[i];
		}
	}
}
}

//质因子分解
namespace compose {
	
//暴力分解 O(sqrt(n))
inline void get_pactor() {
	std::cin >> n, std::cout << n << "=";
	for (int i = 2; i <= sqrt(n); ++i) {
		while (n % i == 0) {
			if (n == i) std::cout << i, exit(0);
			else std::cout << i << "*", n /= i;
		}
	}
	if (n != 1) std::cout << n;
}
}

//扩展欧几里得 
namespace extand_gcd() {

//扩欧 O(logn)最后的(x % b + b) % b是满足ax = 1(mod b)的最小x 
long long a, b, x, y, temp;
inline void ext_gcd(long long a, long long b) {
	if (b == 0) x = 1, y = 0;
	else ext_gcd(b, a % b), temp = x, x = y, y = temp - a / b * y; 
}
}

//快速幂 & 快速乘 
namespace mul_pow {

//O(log n)快速乘 
long long n, m, mod;
inline long long mod_mul(long long a, long long b) {
	long long ans = 0;
	for (; b; b >>= 1, a = (a + a) % mod)
		if (b & 1) ans = (ans + a) % mod;
	return ans;
}

//O(1)快速乘 
inline long long mod_mul(long long a, long long b) {
	return (a * b - (long long)((long double)a / mod * b) * mod + mod) % mod;
}

//O(logn)快速幂 
inline long long mod_pow(long long a, long long b) {
	long long ans = 1;
	for (; b; b >>= 1, a = mod_mul(a, a))
		if (b & 1) ans = mod_mul(ans, a);
	return ans;
}
}

//组合数 
namespace combination {

//O(n ^ 2)组合数递推,方便取模 
const int MAXN = 1000 + 10;
const int mod = 1000000000 + 7;
int c[MAXN][MAXN];
inline void get_c(int n) {
	for (int i = 0; i <= n; ++i) c[i][0] = 1, c[i][i] = 1;
	for (int i = 2; i <= n; ++i)
		for (int j = 1; j < i; ++j)
			c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod;
}

//O(n)预处理阶乘和阶乘逆元,然后O(1)询问组合数 
int fac[MAXN], inv[MAXN];
inline void get_c(int n) {
	fac[0] = 1;
	for (int i = 1; i <= n; ++i) fac[i] = (long long)fac[i - 1] * i % mod;
	inv[n] = mod_pow(fac[n], mod - 2);
	for (int i = n - 1; i >= 0; --i) 
		inv[i] = (long long)inv[i + 1] * (i + 1) % mod;
}

inline int c(int n, int m) {
	return (long long)fac[n] * inv[m] % mod * inv[n - m] % mod;
}
}

//进制转换 
namespace radix_change {

//十进制转任意进制 
inline void radix_10_to_a(int num, int radix) {
	static int sum[100], cnt;
	while (num) sum[++cnt] = num % radix, num /= radix;
	for (int i = cnt; i >= 1; --i) 
		if (sum[i] >= 10) std::cout << (char)(sum[i] + 'A' - 10);
	else std::cout << sum[i];
	return 0;
}

//任意进制转十进制 
inline void radix_a_to_10(int radix, char *s) {
	static int cnt, y;
	cnt = strlen(s + 1);
	for (int i = 1, y = 0; i <= cnt; ++i) {
		if (isdigit(s[i])) y = y * radix + s[i] - '0';
		else y = y * radix + s[i] - 'A' + 10;
	}
	std::cout << y;
}
}

//高精度 
namespace big_integer {

 
const int MAXN = 200 + 10;
const int DIGIT = 1000000000;
//压9位的简单高精度类 
struct big_integer {
	long long a[MAXN];
	int len;
	
	//将big_integer初始化为long long or string代表的数字 
	big_integer(long long s = 0) {
		len = 0, memset(a, 0, sizeof(a));
		do a[++len] = s % DIGIT, s /= DIGIT;
		while (s);
	}
	
	big_integer(char *s) {
		len = 0, memset(a, 0, sizeof(a));
		int s_len = strlen(s + 1);
		long long t = 0, k = 1;
		for (int i = s_len; i >= 1; --i) {
			t = t + (s[i] ^ '0') * k, k = ((k << 2) + k << 1);
			if (k == DIGIT) a[++len] = t, k = 1, t = 0;
		}
		if (t != 0) a[++len] = t;
	}
	
	//重载方括号b[i] = b.a[i]; 
	inline long long & operator [] (const int &c) {
		return a[c];
	}
	
	//重载方括号b[i] = b.a[i]; 
	inline const long long & operator [] (const int &c) const {
		return a[c];
	}
	
	//重载 <  
	inline bool operator < (const big_integer &b) const {
		if (len != b.len) return len < b.len;
		for (int i = len; i >= 1; --i) 
			if (a[i] != b[i]) return a[i] < b[i];
		return false;
	}
	
	//高精 + 高精,重载 +,返回高精和 
	inline big_integer operator + (const big_integer &b) const {
		big_integer c;
		for (int i = 1; i <= len || i <= b.len; ++i)
			c[i] += a[i] + b[i], c[i + 1] += c[i] / DIGIT, c[i] %= DIGIT;
		c.len = std::max(len, b.len) + 2;
		while (c[c.len] == 0) c.len--;
		return (c.len) ? (0) : (c.len = 0), c;
	}
	
	//高精 * 高精,重载 *,返回高精积 
	inline big_integer operator * (const big_integer &b) const {
		big_integer c;
		for (int i = 1; i <= len; ++i)
			for (int j = 1; j <= b.len; ++j) {
				int pos = i + j - 1;
				c[pos] += a[i] * b[j], c[pos + 1] += c[pos] / DIGIT;
				c[pos] %= DIGIT;
			}
		c.len = len + b.len + 3;
		while (c[c.len] == 0) c.len--;
		return (c.len) ? (0) : (c.len = 1), c;
	}
	
	//高精 - 高精,重载 -,返回高精差,默认减数 > 被减数 
	inline big_integer operator - (const big_integer &b) const {
		big_integer c;
		for (int i = 1; i <= len; ++i)
			c[i] += a[i] - b[i], (c[i] < 0) ? (c[i] += DIGIT, c[i + 1]--) : 0;
		c.len = len;
		while (c[c.len] == 0) c.len--;
		return (c.len) ? (0) : (c.len = 1), c;
	}
	
	//高精 / 单精,重载 /,返回高精商 
	inline big_integer operator / (const long long b) const {
		big_integer c;
		long long t = 0;
		for (int i = len; i >= 1; --i)
			c[i] = (a[i] + t * DIGIT) / b, t = (a[i] + t * DIGIT) % b;
		c.len = len;
		while (c[c.len] == 0) c.len--;
		return (c.len) ? (0) : (c.len = 1), c;
	}
	
	//高精 % 单精, 重载%,返回单精 
	inline big_integer operator % (const long long b) const {
		return *this - *this / b * b;
	}
	
	//输出 
	inline void write() const {
		printf("%lld", a[len]);
		for (int i = len - 1; i >= 1; --i) printf("%09lld", a[i]);
	}
} ;

//重载cin, cin >> (big_integer)a, 直接读入一个字符串,然后将a赋值为字符串 
inline std::istream & operator >> (std::istream &a, big_integer &b) {
	static char s[MAXN << 4];
	scanf("%s", s + 1), b = s;
	return a;
}

//重载cout, cout << (big_integer)b, 输出b,利用write() 
inline std::ostream & operator << (std::ostream &a, const big_integer &b) {
	b.write();
	return a;
}
}

//高斯消元
namespace gauss {

const int MAXN = 100 + 10;
int n;
double f[MAXN][MAXN], ans[MAXN];
//f[i][j]表示第i个等式中第j个变量的系数,f[i][n + 1]表示第i个等式的值 
inline void solve() {
	for (int i = 1; i <= n; ++i) {
		int pos = -1;
		for (int j = i; j <= n; ++j) 
			if (f[j][i] != 0) {
				pos = j;
				break ;
			}
		std::swap(f[pos], f[i]);
		for (int j = i + 1; j <= n; ++j) {
			double t = f[j][i] / f[i][i];
			for (int k = i; k <= n + 1; ++k)
				f[j][k] -= t * f[i][k];
		}
	}
	for (int i = n; i >= 1; --i) {
		ans[i] = f[i][n + 1] / f[i][i];
		for (int j = 1; j < i; ++j)
			f[j][n + 1] -= f[j][i] * ans[i];
	}
	for (int i = 1; i <= n; ++i) std::cout << int(ans[i] + 0.5) << " ";
}
}

//矩阵乘法 & 矩阵快速幂
namespace matrix {

const int MAXN = 200 + 10;
const int mod = 1000000000 + 7;
//矩阵类 
struct matrix {
	int a[MAXN][MAXN];
	int n;
	matrix() {}
	matrix(int n) : n(n) {
		for (int i = 1; i <= n; ++i)
			for (int j = 1; j <= n; ++j)
				a[i][j] = 0;
	}
	
	//重载 * , 矩阵乘法 
	inline matrix operator * (const matrix &b) const {
		matrix ans(n);
		for (int i = 1; i <= n; ++i)
			for (int k = 1; k <= n; ++k)
				for (int j = 1; j <= n; ++j)
					ans.a[i][j] = (ans.a[i][j] + a[i][k] * b.a[k][j]) % mod;
		return ans;
	}
	
	//重载 ^ ,矩阵快速幂 
	inline matrix operator ^ (int b) const {
		matrix ans(n), a = *this;
		for (int i = 1; i <= n; ++i) ans.a[i][i] = 1;
		for (; b; b >>= 1, a = a * a) 
			if (b & 1) ans = ans * a;
		return ans;
	}
};
}

查看评论
    个人资料
    专栏达人 持之以恒
    等级:
    访问量: 2万+
    积分: 2169
    排名: 2万+
    博客专栏
    最新评论