staticvoidget_divisors(int x){ ArrayList<Integer> list = new ArrayList<>(); for (int i = 1; i <= x / i; i++) { if (x % i == 0) { list.add(i); if (i != x / i) list.add(x / i); } } Collections.sort(list);//排序复杂度logn*loglogn for(int i : list){ System.out.print(i + " "); } System.out.println(); }
publicclassgetDivisors_number{ staticint mod = (int) (1e9 + 7); publicstaticvoidmain(String[] args){ Map<Integer, Integer> map = new HashMap<>();//创建一个哈希表 Scanner sc = new Scanner(System.in); int n = sc.nextInt();
while(n-- != 0){ int x = sc.nextInt(); for(int i = 2; i <= x / i; i++){ while(x % i == 0){ x /= i; map.put(i, map.getOrDefault(i, 0) + 1); } } if(x > 1)map.put(x, map.getOrDefault(x, 0) + 1); }
publicclassgetDivisors_Sum{ staticint mod = (int) (1e9 + 7); publicstaticvoidmain(String[] args){ Map<Integer, Integer> map = new HashMap<>();//创建一个哈希表 Scanner sc = new Scanner(System.in); int n = sc.nextInt();
while(n-- != 0){ int x = sc.nextInt(); for(int i = 2; i <= x / i; i++){ while(x % i == 0){ x /= i; map.put(i, map.getOrDefault(i, 0) + 1); } } if(x > 1)map.put(x, map.getOrDefault(x, 0) + 1); }
long res2 = 1L; for(Integer p : map.keySet()){ int a = map.get(p); long t = 1L; while(a -- != 0)t = (t * p + 1) % mod; res2 = res2 * t % mod; } System.out.println(res2); } }
(4)最大公因数
辗转相除法O(logn):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
import java.util.Scanner;
publicclassgcd{ staticintGCD(int a, int b){ return b == 0 ? a : GCD(b, a % b); }
publicstaticvoidmain(String[] args){ Scanner sc = new Scanner(System.in); int n = sc.nextInt(); while(n-- != 0){ int a = sc.nextInt(); int b = sc.nextInt(); System.out.println(GCD(a, b)); } } }
欧拉函数
特别的,1和任何n互质,n和n不互质
(互质:两个数的公因数只有1)
分解质因数
证明:
容斥原理:
从1~N中去掉p1,p2,…,pk的所有倍数
加上所有pi*pj的倍数
减去所有pi pj pk的倍数
….
代码:
复杂度O(sqrt(n))
1 2 3 4 5 6 7 8 9 10 11
staticintphi(int x){ int res = x; for(int i = 2; i <= x / i; i++){ if(x % i == 0) { res = res / i * (i - 1); while (x % i == 0) x /= i; } } if(x > 1)res = res / x * (x - 1); return res; }
staticint N = 1000010; staticint[] primes = newint[N]; staticint[] phi = newint[N]; staticboolean[] st = newboolean[N]; staticint cnt;
staticlongget_Euler(int n){ long res = 1; for (int i = 2; i <= n; i++) { if (!st[i]) { primes[cnt++] = i; phi[i] = i - 1;//针对质数的欧拉函数 } for (int j = 0; primes[j] <= n / i; j++) { st[i * primes[j]] = true; if (i % primes[j] == 0) {//pj是i的最小质因数 phi[i * primes[j]] = phi[i] * primes[j]; break; } phi[i * primes[j]] = phi[i] * (primes[j] - 1);//pj小于i的最小质因数 } }
for(int i = 1; i <= n; i++){ res += phi[i]; } return res; }
补充:
欧拉定理:
若a与n互质,则有
费马小定理:
当p为质数,整数a不是p的倍数(互质的更弱条件)时:
快速幂
快速求出a^k mod p的结果
复杂度:O(log k)
1 2 3 4 5 6 7 8 9
staticintPMI(int a, int b, int p){//a ^ b % p int res = 1 % p; while(b != 0) { if ((b & 1) == 1) res = (int)((long)res * a % p); b >>= 1; a = (int) ((long)a * a % p); } return res; }
扩展欧几里得算法
裴蜀定理:对于任意正整数a,b,那么一定存在非零整数x,y,使得:ax + by = gcd(a,b)
publicclassexgcd{ staticint[] x = newint[1]; staticint[] y = newint[1];
publicstaticvoidexGCD(int a, int b, int[] x, int[] y){ if (b == 0) {//递归出口(找到了最大公约数) x[0] = 1; y[0] = 0; return; } exGCD(b, a % b, y, x); y[0] -= (a / b) * x[0]; }
publicstaticvoidmain(String[] args){ Scanner sc = new Scanner(System.in); int n = sc.nextInt(); while (n-- != 0) { int a = sc.nextInt(); int b = sc.nextInt(); exGCD(a, b, x, y); System.out.println(x[0] + " " + y[0]); } } }
publicclassMain{ staticint[] x = newint[1]; staticint[] y = newint[1]; publicstaticintexGCD(int a, int b, int[] x, int[] y){ if (b == 0) {//递归出口(找到了最大公约数) x[0] = 1; y[0] = 0; return a; } int d = exGCD(b, a % b, y, x); y[0] -= (a / b) * x[0]; return d; } publicstaticvoidmain(String[] args)throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); int n = Integer.parseInt(br.readLine()); while(n -- != 0){ String[] s = br.readLine().split(" "); int a = Integer.parseInt(s[0]); int b = Integer.parseInt(s[1]); int m = Integer.parseInt(s[2]); int d = exGCD(a, m, x, y); if(b % d == 0)System.out.println((long)x[0] * b / d % m); else System.out.println("impossible"); } } }
publicclassMain{ staticint N = 110; staticint n; staticdouble[][] a = newdouble[N][N];
staticdouble eps = 1e-6;
staticintGauss(){ int c, r; for (c = 0, r = 0; c < n; c++) {//枚举每一列c(n列) int t = r; for (int i = r; i < n; i++) if (Math.abs(a[i][c]) > Math.abs(a[t][c])) t = i;
staticintqmi(int a, int b, int p){ int res = 1 % p; while (b != 0) { if ((b & 1) == 1) res = (int) ((long) res * a % mod); a = (int) ((long) a * a % p); b >>= 1; } return res; }
publicstaticvoidmain(String[] args)throws IOException { //预处理 fact[0] = infact[0] = 1; for (int i = 1; i < N; i++) { fact[i] = (int) ((long) fact[i - 1] * i % mod); infact[i] = (int) ((long) infact[i - 1] * qmi(i, mod - 2, mod) % mod);//逆元 } BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); int n = Integer.parseInt(br.readLine()); while (n-- != 0) { String[] s = br.readLine().split(" "); int a = Integer.parseInt(s[0]); int b = Integer.parseInt(s[1]); System.out.println(((long)fact[a] * infact[b]) % mod * infact[a - b] % mod); } } }
staticintqmi(int a, int b, int p){ int res = 1 % p; while (b != 0) { if ((b & 1) == 1) res = (int) ((long) res * a % mod); a = (int) ((long) a * a % p); b >>= 1; } return res; }
publicstaticvoidmain(String[] args)throws IOException { //预处理 fact[0] = infact[0] = 1; for (int i = 1; i < N; i++) { fact[i] = (int) ((long) fact[i - 1] * i % mod); } // System.out.println(fact[N-1]); infact[N - 1] = qmi(fact[N - 1], mod - 2, mod); // System.out.println(infact[N-1]); for(int i = N - 2; i >= 1; i--){ infact[i] = (int)((long)infact[i+1] * (i + 1) % mod); } BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); int n = Integer.parseInt(br.readLine()); while (n-- != 0) { String[] s = br.readLine().split(" "); int a = Integer.parseInt(s[0]); int b = Integer.parseInt(s[1]); System.out.println(((long)fact[a] * infact[b]) % mod * infact[a - b] % mod); } } }
staticintqmi(int a, int b){ int res = 1 % p; while(b != 0){ if((b & 1) == 1)res = (int)((long)res * a % p); a = (int)((long) a * a % p); b >>= 1; } return res; } staticintC(long a, long b){ int res = 1; for(int i = 1, j = (int)a; i <= b; i++, j--){ res = (int) ((long) res * j % p); res = (int) ((long) res * qmi(i, p-2) % p); } return res; } staticintlucas(long a, long b){ if(a < p && b < p){ return C(a, b); } return (int) ((long) lucas(a/p, b/p) * C(a % p, b % p) % p); }
publicstaticvoidmain(String[] args)throws IOException{ BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); int n = Integer.parseInt(br.readLine()); while(n -- != 0){ String[] s = br.readLine().split(" "); long a = Long.parseLong(s[0]); long b = Long.parseLong(s[1]); p = Integer.parseInt(s[2]);
publicclasscombination04{ staticint N = 5050; staticint[] primes = newint[N];//记录a范围内的所有素数 staticboolean[] st = newboolean[N]; staticint cnt = 0; staticint[] sum = newint[N];//求Cab中对应存在每一个素数的指数
staticvoidget_primes(int n){//线性筛 for (int i = 2; i <= n; i++) { if (!st[i]) primes[cnt++] = i; for (int j = 0; primes[j] <= n / i; j++) { st[primes[j] * i] = true; if (i % primes[j] == 0) break; } } }
staticintget(int n, int p){//求n!中p的个数 int res = 0; while(n != 0){ res += n / p; n /= p; } return res; }
publicstaticvoidmain(String[] args){ Scanner sc = new Scanner(System.in); int a = sc.nextInt(); int b = sc.nextInt(); get_primes(a);
for (int i = 0; i < cnt; i++) { int p = primes[i]; sum[i] = get(a, p) - get(b, p) - get(a - b, p); } BigInteger res = new BigInteger("1"); for (int i = 0; i < cnt; i++) { for (int j = 0; j < sum[i]; j++){ res = res.multiply(new BigInteger(String.valueOf(primes[i]))); } } System.out.println(res); } }
卡特兰数
适用于较多的问题:
例如:
给定 n 个 0 和 n 个 1,它们将按照某种顺序排成长度为 2n 的序列,求它们能排列成的所有序列中,能够满足任意前缀序列中 0 的个数都不少于 1 的个数的序列有多少个
publicclassCatalan{ staticint mod = (int)1e9+7; staticintqmi(int a, int b){//费马小定理 前提:p为质数 int res = 1 % mod; while(b != 0){ if((b & 1) != 0) res = (int)((long)res * a % mod); b >>= 1; a = (int)((long)a * a % mod); } return res; }
publicstaticvoidmain(String[] args){ Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int a = 2 * n; int res = 1; for(int i = 1, j = a; i <= n; i++, j--){ res = (int)((long)res * qmi(i, mod-2) % mod);//一定要注意类型转换 res = (int)((long)res * j % mod); } res = (int)((long)res * qmi(n+1, mod-2) % mod); System.out.println(res); } }
容斥原理
公理:(二项式定理得到 (1+x)^n)
复杂度:O(2^n)
例题:
给定一个整数 n 和 m 个不同的质数 p1, p2,…,pm。 请你求出 1∼n 中能被 p1,p2,…,pm 中的至少一个数整除的整数有多少个。