求约数

试除法

  • 从小到大枚举,找到一个数的所有的约数
  • 大的部分通过 n / i 实现
  • 时间复杂度
 //vector实现
 
 vector<int> get_divisors(int n)
 {
   	vector<int> res;
   	
   	for(int i = 1; i <= n / i; i ++)
   		if(n % i == 0)
   	  {
   			res.push_back(i);
   			if(i != n / i)  res.push_back(n / i);  // 判断i与 n/i 不同,避免重复
   	  }
 
   	sort(res.begin(), res.end());
   	
   	return res;
 }

约数个数

做一些延申,当 , 有 取值为 ,则每个个数可以选择,都构成 d 为 n 的约数(正因数) 所以 约数个数为

  • int 范围内约数个数最大的是 1500 左右(这个级别)

实现

  • 先分解质因数,记录下指数
  • 再 指数 + 1 相乘得到结果
  unordered_map primes;
  
  for(int i = 2; i <= x / i; i ++)
  {
	 while(x % i == 0)
	 {
		x /= i;  //这步操作后,当x最后一次被整除,x会等于1,所以最后的特判要大于1
		primes[i] ++;
	 }
  }
		  
  if(x > 1)  primes[x] ++;  //特判大于\sqrt(n)的质数
  
  LL ans = 1;
  for(auto i: primes)  ans *= i.second + 1

约数之和

理论

  • 依旧是延申,可以知道每个约数其实就是的不同组合
  • 所以可以得到 约数之和 就是
  • 由乘法分配律展开就能得到约数之和

实现

  • 利用分解质因数求p和\alpha
  • 再利用 t = t * p + 1 的循环实现
[[include]] <unordered_map>
int main()
{
   unordered_map<int, int> primes;
   int x;
   cin >> x;
   for(int i = 2; i <= x / i; i ++)
 {
   	while(x % i == 0)
     {
   		x /= i;
   		primes[i] ++;
     }
}
 
   if(x > 1) primes[x] ++;  //别忘了检查
 
   for(auto i: primes)
 {
   	int p = i.first, a = i.second;
   	int t = 1;
   	while(a --)  t = (t * p + 1) % m;  //如果有要求
   ans = ans * t % m;
 }
 
   cout << ans << endl;
}

最大公约数

理论

  • 欧几里得算法 ^bd4826 即 a与b的最大公约数等于b和a模b的最大公约数
  • 证明 a模b等于
    • 又a与b的最大公约数是 b与 的最大公约数(假如a与b的最大公约数为c,c同时可以整除b,和,因为[a/b]是整数,且比a小,都是c的倍数,则没有比c更大的约数(有的话a和b就有更大的约数了)

实现

int gcd(int a, int b)
{
	return b? gcd(b, a % b) : a;
//实现为递归,当b为0时,a的值是其最大公约数,也是其所有递归过程的最大公约数
}