数论模板1
来源:互联网 发布:日语翻译软件 知乎 编辑:程序博客网 时间:2024/05/20 16:08
参照Stanford Team Notebook
加入get_prime函数
修正chinese_reminder变量顺序错误
//无全局变量#include <cstdio>#include <cstring>#include <cstdlib>#include <iostream>#include <vector>#include <algorithm>using namespace std;typedef vector<int> VI;typedef pair<int, int> PII;//O(n)打1..n的素数表,附带因子分解功能, factor[i]给出i的最小素因子(factor[1] = 1)void get_prime(int n, VI & prime, VI & factor){ prime.clear(); factor.resize(n + 1); for (int i = 1; i <= n; i++) factor[i] = i; for (int i = 2; i <= n; i++) { if (i == factor[i]) prime.push_back(i); for (int j = 0; j < prime.size() && prime[j] * i <= n; j++) { factor[i * prime[j]] = prime[j]; if (i % prime[j] == 0) break; } }}//a对b取正数模int mod(int a, int b){ return ((a % b) + b) % b;}//最大(正)公约数, 非递归int gcd(int a, int b){ int tmp; while(b) { a %= b; tmp = a; a = b; b = tmp; } if (a < 0) a = -a; return a;}//最小(正)公倍数(注意可能会超int范围)int lcm(int a, int b){ int ans = a / gcd(a, b) * b; if (ans < 0) ans = -ans; return ans;}//非递归扩展欧几里得, 求解ax + by = gcd(a, b)int extended_euclid(int a, int b, int & x, int & y){ int xx = y = 0, yy = x = 1; while(b) { int q = a / b; int t = b; b = a % b; a = t; t = xx; xx = x - q * xx; x = t; t = yy; yy = y - q * yy; y = t; } if (a < 0) { a = -a; x = -x; y = -y; } return a;}//求乘法逆元x(ax = 1 (mod n)), 无逆元则输出-1int mod_inverse(int a, int n){ int x, y; int d = extended_euclid(a, n, x, y); if (d != 1) return -1; else return mod(x, n);}//求解模线性方程ax = b (mod n), 返回x的所有可能取值(无序)VI mod_linear_equation(int a, int b, int n){ int x, y; VI ret; int d = extended_euclid(a, n, x, y); if (b % d == 0) { x = mod(x * (b / d), n); for (int i = 0; i < d; i++) ret.push_back(mod(x + i * (n / d), n)); } return ret;}//求解线性丢番图方程ax + by = c, 成功返回0, 失败返回-1int linear_diophantine(int a, int b, int c, int & x, int & y){ int d = extended_euclid(a, b, x, y); if (c % d != 0) return -1; else { x *= c / d; y *= c / d; return 0; }}//中国剩余定理(x = a1 (mod x1),x = a2(mod x2), 不要求x1与x2互质//返回值意义为x = first (mod second),失败则返回的second为-1PII chinese_remainder(int a1, int x1, int a2, int x2){ int n1, n2; if (linear_diophantine(x1, -x2, a2 - a1, n1, n2) == -1) return make_pair(0, -1); else return make_pair(mod(a1 + n1 * x1, lcm(x1, x2)), lcm(x1, x2));}//中国剩余定理完全体,求解方程组x = ai (mod xi), i = 0...n - 1, 不要求模数互质//返回值意义为x = first (mod second),失败则返回的second为-1PII chinese_remainder(const VI & a, const VI & x, int n){ PII ret = make_pair(a[0], x[0]); for (int i = 1; i < n; i++) { ret = chinese_remainder(ret.first, ret.second, a[i], x[i]); if (ret.second == -1) break; } return ret;}int main(){// printf("%d\n", gcd(14, 30));// printf("%d\n", lcm(14, 30));// int x, y;// printf("%d\n", extended_euclid(15, 34, x, y));// printf("%d %d\n", x, y);// printf("%d\n", mod_inverse(9, 19));// VI ans = mod_linear_equation(14, 30, 100);// for (int i = 0; i < ans.size(); i++)// printf("%d\n", ans[i]);// if (linear_diophantine(7, 2, 5, x, y) != -1)// printf("solution: x = %d, y = %d\n", x, y);// else// printf("no solution\n");// int aa[5] = {2, 3, 2, 3, 5},// xx[5] = {3, 5, 7, 4, 6};// VI avi(aa, aa + 5), xvi(xx, xx + 5);// PII ans2;// ans2 = chinese_remainder(avi, xvi, 3);// cout << ans2.first << " " << ans2.second << endl;// VI pri, fac;//// 此处可以将pri和fac声明在main函数内,vector内的元素在堆上// get_prime(100, pri, fac);// for (int i = 0; i < pri.size(); i++)// printf("%d%c", pri[i], (i == pri.size() - 1) ? '\n' : ' ');// for (int i = 1; i < fac.size(); i++)// printf("%d : %d\n", i, fac[i]); return 0;}
- 数论模板1
- 模板之数论大全1
- 数论模板(总结1)
- 数论模板
- 数论模板
- 数论模板
- 数论-模板
- 【数论模板】
- 数论模板
- [模板] 数论
- 数论模板
- 数论模板
- 数论模板
- 数论模板
- 数论[模板]
- 数论模板
- 数论 基本模板
- 【模板】 简单数论
- {{PHP}}变量作用域测试(待续)
- sp9
- jboss启动异常解决方法
- sp10
- 自己动手让Visual Studio的Win32向导支持生成对话框程序
- 数论模板1
- 一种编译错误的解决办法。/usr/include/linux/errno.h:4:23: fatal error: asm/errno.h: No such file or directory
- 03 orange kernel
- Ubuntu在终端中使用su切换到root权限
- POJ 3270 / HDU 2838 - Cow Sorting
- SQL语言基础(四)
- 关于提高.net应用程序效率的一些经验总结
- 《Red5 用户参考手册》之十三:Red5 核心技术第六章 集群
- 景深计算器