数论板子
来源:互联网 发布:iphone 投影到mac 编辑:程序博客网 时间:2024/06/07 08:07
//筛法求MAXN范围以内的素数表,其中需要借用一个bool数组vis void prime_table() { int i,j; for(i = 2;i <= MAXN;i++) { if(!vis[i]) { prime[++cnt] = i; //cnt为素数计数器 for(j = i*i;j <= MAXN;j += i) vis[j] = true; } } }
//高效算法同时打出prime表与phi表,比单独用筛法打出phi表与prime表快3倍左右void prime_phi_table(){ int i,j; phi[1] = 1; for(i = 2;i <= MAXN;i++) { if(!vis[i]) { prime[++cnt] = i; phi[i] = i-1; } for(j = 1;j <= cnt && i * prime[j] <= MAXN;j++) { vis[i * prime[j]] = true; if(i % prime[j] == 0) { phi[i * prime[j]] = phi[i] * prime[j]; break; } else phi[i * prime[j]] = phi[i] * (prime[j] - 1); } }}
//求n的欧拉函数值 int phi(int n) { int t = sqrt(n + 0.5); int ans = 1; for(int i = 2;i <= t;i++) { if(n % i == 0) { ans *= (i-1); n /= i; while(n % i == 0) { ans *= i; n /= i; } } if(n == 1) break; } if(n > 1) ans *= (n-1); return ans; }
//求a与b的最大公约数,其中b > a int gcd(int a,int b) { if(a > b) swap(a,b); while(a) { int t = b % a; b = a; a = t; } return b; }
//扩展欧几里得,ax + by = c,求出x,y的一组整数解,d = gcd(a,b),当 c % d != 0时,无整数解 void exgcd(int a,int b,int &d,int &x,int &y) { if(!b) {d = a; x = 1; y = 0;} else { exgcd(a%b,a,d,y,x); y -= x*(a/b); } }
<pre name="code" class="cpp">//在上述不定方程中,若方程为ax + by = gcd(a,b),当求出一组整数解x0,y0后 //关于x,y的通解则有:x = x0 + b/d * k , y = y0 - a/d * t (t为任意整数) [cpp] view plain copy<pre name="code" class="cpp">//由于模运算的特殊性,在计算(a / b) % m 时,当a、b太大需要事先取模,此时该式不能直接写为: // ((a % m) / (b % m)) % m // 而是需要先算出 ax≡1(mod m),此时x为a的逆元。这个式子等价于ax + my = 1(此时gcd(a,b)必须为1,否则无解) // 此时使用扩展欧几里得即可解决:exgcd(a,m,d,x,y);当m为质数时,x = (a^(m-2)) % m; //但求出来的x可能为负数,需要写成(x + m) % m // 最终式子为 (a / b) % m = a * x % m
//对整数n进行唯一分解,A[cnt].prime为n的第cnt个质因子,A[cnt].num为该质因子的指数 void dissolve(int n) { int i; int t = sqrt(n + 0.5); for(i = 2;i <= t;i++) { if(n % i == 0) { cnt++; A[cnt].prime = i; while(n % i == 0) { A[cnt].num++; n /= i; } } if(n == 1) break; } if(n > 1) //若n为质数 { cnt++; A[cnt].prime = n; A[cnt].num = 1; } }
//求1~n行的组合数,即杨辉三角表,注意,为了防止数组越界,此时C(0,0)为数组第一行,且第n行代表C(n-1,k) void Make_up_num_table(int n) { C[1][1] = 1; C[2][1] = 1; C[2][2] = 1; for(int i = 3;i <= n;i++) for(j = 1;j <= i;i++) C[i][j] = C[i-1][j-1] + C[i-1][j]; } [cpp] view plain copy//求第n行的组合数,和杨辉三角的区别是这个只求一行但是为O(n)的时间复杂度 //注意,这个函数出于求解方便,第n行代表的是C(n,k)且是从0开始存,与上一个函数不同 void Make_up_num(int n) { A[0] = 1; for(int i = 1;i <= n;i++) A[i] = A[i-1] * (n - i + 1) / i; }
阅读全文
0 0
- 数论板子
- 数论板子
- ACM数论 板子
- 数论板子(持续更新
- java 数论板子
- 数论&&快排&&dp板子
- 【数论板子】_我也就会这些
- 数论 图论板子&&数据结构
- 一锅大杂烩——各种数论の板子
- 板子
- 板子
- hiho 1298 数论·五 欧拉函数 (欧拉函数筛选板子)
- 数论
- 数论
- 数论
- 数论
- 数论
- 数论
- 【基础算法】(06)五大常用算法之二:动态规划
- 简单c排序之冒泡排序法
- 后台截图(一)
- C/C++中的字面值常量
- CentOS Linux系统搭建SVN server服务
- 数论板子
- leetcod第一题和第二题
- 机器学习流程--ML之一
- 线性代数--线性无关3
- Qt学习: QPaintEvent和QMouseEvent的简单程序示例
- 路由器与交换机的区别与联系
- 网络的七层架构OSI
- const在C语言和C++中的区别
- R语言处理气象数据:NetCDF格式数据的读写