ACM_模板_求一个数的所有因子和(预处理打表)

本文介绍了一种高效的算法来求解一个数n的所有因数之和,通过改变思路从求一个数的因数和转变为求一个数在一定范围内作为哪些数的因数,这种方法可以大大减少计算过程中的无效遍历,提高效率。

对于求一个数n的所有因数和,可能很多人的第一想法是遍历1~sqrt(n)来找其因数,但是这样做不好的地方就是我们可能会遍历大量没有用的数,浪费了很多时间,所以我们与其是求一个数的所有因数和不如求一个数在一个范围内是哪些数的因数,这样求解就可以省去大量的时间,从而达到预处理打表的效果。

#include <cstdio>
const int maxn = 500000+2;
int sum[maxn];
int main()
{
	for(int i=1; i<maxn; i++)
		for(int j=1; i*j<maxn; j++)
			sum[i*j] += i;
	int a;
	while(scanf("%d",&a)!=EOF)
		printf("%d\n",sum[a]);
	return 0;
}


<think>首先,用户查询是:“我想查找ACM论相关的代码模板 请问ACM论代码模板”。我需要基于系统级指令用户提供的引用来回答。 系统级指令关键点: - 所有行内学表达式使用$...$格式。 - 独立公式使用$$...$$格式并单独成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 引用末尾添加标识如[^1]。 用户提供了几个引用: - [^1]:关于模逆元的计算,使用快速幂或扩展欧几里得算法。 - [^2]:莫比乌斯反演的题目公式。 - [^3]:预处理阶乘逆元,用于组合的计算。 - [^4]:欧拉函的定义、性质计算算法。 用户的上一次查询是“查找ACM论相关的代码模板”,所以我需要提供一个清晰的、结构化的回答,涵盖常见的ACM模板。 核心元素: - **模逆元计算**:快速幂方法(qmi)扩展欧几里得方法。 - **组合计算**:预处理阶乘其逆元。 - **欧拉函**:朴素方法线性筛法。 - **快速幂算法**:用于快速计算幂模素。 - **其他常见模板**:如最大公约(GCD)、质因数分解、线性筛质等。 由于引用中没有提到所有,我应该补充常见模板,确保回答全面但基于引用优先。 结构回答: 1. **引言**:简要介绍ACM论常见算法。 2. **核心模板**:逐一列出代码模板。 3. **格式**:代码块使用Markdown格式,学表达式正确。 4. **引用**:在相关部分添加引用标识。 5. **相关问题**:结束时生成相关问题。 列出模板: - **快速幂算法**:引用[^1][^3]中都有。 - **模逆元计算**:引用[^1]。 - **组合计算**:引用[^3]。 - **欧拉函计算**:引用[^4]。 - **其他**:GCD、线性筛质、扩展欧几里得(引用[^1]中提到)。 添加扩展欧几里得,因为它用于模逆元。 回答结构: - 逐步呈现每个模板。 - 每个模板先简短描述,然后代码块。 - 确保LaTeX正确。 学表达式: - 行内:如$gcd(n, p) = 1$。 - 独立:如欧拉函性质。 生成相关问题: - 如ACM论的应用、优化等。 最终输出: - 中文回答。 - 相关问题列表。 </think>以下是针对ACM论常见代码模板的整理。ACM论题目通常涉及质、模运算、组合学等核心算法。我基于您提供的引用内容(参考[^1][^2][^3][^4]),并结合ACM竞赛的常见需,总结了以下关键模板模板均使用C++语言实现,并确保语法正确。每个模板包括简要说明、适用条件代码实现。 ### 1. **快速幂算法** 快速幂用于高效计算 $a^k \mod p$,时间复杂度 $O(\log k)$。适用条件:$p$ 为质(非质时需用扩展欧几里得)。 ```cpp typedef long long LL; LL qmi(LL a, LL k, LL p) { // a: 底, k: 指, p: 模 LL res = 1 % p; while (k) { if (k & 1) res = res * a % p; a = a * a % p; k >>= 1; } return res; } /* 示例:计算 2^100 mod 1000000007 qmi(2, 100, 1000000007); */ ``` ### 2. **模逆元计算** 模逆元用于解 $n^{-1} \mod p$(即 $n \cdot inv \equiv 1 \mod p$)。方法包括快速幂逆元(要 $p$ 质且 $gcd(n, p) = 1$)扩展欧几里得逆元(通用)。 - **快速幂逆元**(引用[^1]): ```cpp LL inv(LL n, LL p) { // n: 待逆元的, p: 模 return qmi(n, p - 2, p); // 利用费马小定理 } ``` - **扩展欧几里得逆元**(引用[^1]): ```cpp LL exgcd(LL a, LL b, LL &x, LL &y) { // 解 ax + by = gcd(a, b),返回gcd if (b == 0) { x = 1, y = 0; return a; } LL d = exgcd(b, a % b, y, x); y -= a / b * x; return d; } LL inv_exgcd(LL n, LL p) { LL x, y; exgcd(n, p, x, y); // 解 nx + py = 1 return (x % p + p) % p; // 确保非负 } ``` ### 3. **组合计算** 预处理阶乘阶乘逆元,用于快速计算 $C_a^b \mod p$(如组合)。时间复杂度:预处理 $O(n)$,查询 $O(1)$。适用条件:$p$ 质且 $a, b \leq N$($N$ 为预处理上限)(引用[^3])。 ```cpp const int N = 1000010; // 预处理上限 const int mod = 998244353; // 常用模,可替换 LL fact[N], infact[N]; // fact[i]: i的阶乘 mod p; infact[i]: i的阶乘逆元 mod p // 预处理 void init_comb() { fact[0] = infact[0] = 1; for (int i = 1; i < N; i++) { fact[i] = fact[i - 1] * i % mod; infact[i] = infact[i - 1] * qmi(i, mod - 2, mod) % mod; // 使用快速幂逆元 } } // 计算组合 C(a, b) mod p LL comb(int a, int b) { if (b < 0 || b > a) return 0; return fact[a] * infact[b] % mod * infact[a - b] % mod; } ``` ### 4. **欧拉函** 欧拉函 $\phi(n)$ 计算小于等于 $n$ 且与 $n$ 互质的的个。常用方法:朴素法 ($O(\sqrt{n})$ ) 线性筛法 ($O(n \log \log n)$ )(引用[^4])。 - **朴素法**(单次查询): ```cpp int euler(int n) { int res = n; for (int i = 2; i * i <= n; i++) { if (n % i == 0) { res = res / i * (i - 1); // 防止溢出 while (n % i == 0) n /= i; } } if (n > 1) res = res / n * (n - 1); return res; } ``` - **线性筛法**(批量预处理): ```cpp const int Max = 1000010; // 预处理上限 int euler_phi[Max]; void init_euler() { for (int i = 1; i < Max; i++) euler_phi[i] = i; for (int i = 2; i < Max; i++) { if (euler_phi[i] == i) { // i 是质 for (int j = i; j < Max; j += i) { euler_phi[j] = euler_phi[j] / i * (i - 1); // 更新欧拉函值 } } } } ``` ### 5. **莫比乌斯反演相关** 莫比乌斯函常用于处理问题(如引用[^2]中 $\sum \text{lcm}(a_i, a_j)$)。包括莫比乌斯函 $\mu(n)$ 的预处理。 ```cpp const int MAXN = 1000010; int mu[MAXN]; // 莫比乌斯函组 vector<int> primes; // 存储质 bool is_prime[MAXN]; void init_mobius() { fill(is_prime, is_prime + MAXN, true); mu[1] = 1; for (int i = 2; i < MAXN; i++) { if (is_prime[i]) { primes.push_back(i); mu[i] = -1; // 质的莫比乌斯函值为 -1 } for (int j = 0; j < primes.size() && i * primes[j] < MAXN; j++) { is_prime[i * primes[j]] = false; if (i % primes[j] == 0) { mu[i * primes[j]] = 0; // 有平方因子 break; } else { mu[i * primes[j]] = -mu[i]; // 积性函性质 } } } } ``` ### 6. **其他基础模板** - **最大公约 (GCD)**: ```cpp LL gcd(LL a, LL b) { return b ? gcd(b, a % b) : a; } ``` - **最小公倍 (LCM)**: ```cpp LL lcm(LL a, LL b) { return a / gcd(a, b) * b; // 避免溢出 } ``` - **质筛法 (埃氏筛)**: ```cpp const int MAX = 1000010; bool is_prime[MAX]; void init_primes() { fill(is_prime, is_prime + MAX, true); is_prime[0] = is_prime[1] = false; for (int i = 2; i * i < MAX; i++) { if (is_prime[i]) { for (int j = i * i; j < MAX; j += i) { is_prime[j] = false; } } } } ``` ### 注意事项 - 所有模板均假设模 $p$ 在合理范围内(通常 $p \leq 10^9$),并使用 `long long` 防溢出。 - 在ACM中,欧拉定理降幂公式可用于优化幂运算(引用[^4]):若 $a$ $n$ 互质,则 $a^k \mod n = a^{k \mod \phi(n)} \mod n$。 - 这些模板覆盖了大部分ACM论题目,如莫比乌斯反演、组合计模方程解[^1][^2][^3][^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值