整除基本知识

1|0整除基本知识

1|1性质

  • a|bb|c,则 a|c
  • a|bb|c,则 对于任意的整数 xy,有 a|(bx+cy)
  • 对于整数 m0a|bb|a

1|2寻找约数

1|0暴力

for (int i = 1; i <= n; i++) { if (x % i == 0) ans[++cnt] = i; }

1|0优化

约数肯定是成对出现的。

对于 120

2,60

即如果 kn 的约数,那么 nk 也一定是 n 的约数。

不妨设 k 是较小的一个(为了优化枚举时间),那么显然。

knk

kn

那么对 k 枚举,时间复杂度就降低到了 O(n)

int find_divisors(int n, int a[]) { int cnt = 0; for (int k = 1; k * k <= n; k++) { if (n % k == 0) { a[++cnt] = k; if (k != n / k) a[++cnt] = n / k; } } return cnt; }

1|3数列中的倍数数

P2926 USACO08DEC Patting Heads S

从枚举倍数的角度思考:对于一个数 i 若它在原数组中出现了 c[i] 次,那么 i 这个数会对它的每一个倍数产生 c[i] 的贡献。这样就可以通过查询这样产生的贡献的总和来计算答案了,其时间复杂度为:

O(nlogn)

1|0代码:

#include <bits/stdc++.h> using namespace std; const int Maxn=1000100;//数组大小 const int Bignumber=1000000; int n,a[Maxn],c[Maxn],w[Maxn];//n个数,数列,数字统计容器,贡献值 int main() { scanf("%d",&n);//输入 for(int i=1;i<=n;i++) { scanf("%d",&a[i]);//输入数列 c[a[i]]++; } for(int i=1;i<=Bignumber;i++) for(int j=i;j<=Bignumber;j+=i) w[j]+=c[i];//i这个数会对j产生c[i]的贡献 for(int i=1;i<=n;i++) printf("%d\n",w[a[i]]-1);//输出时要把a[i]对自己的贡献减去 return 0; }

1|4快速求因子数

1|0依靠两个结论

  • 一个正整数一定能分解为若干质数 n 次方的乘积。
  • 一个数的因子数等于该数分解为若干质数 n 次方的乘积后每个质数的次方数加一的乘积。

1|0举个例子

120=23×3×5

那么因子数则是 (3+1)×(1+1)×(1+1)=16

1|0代码实现

ll getInShu(ll n) { ll ans = 1; for (int i = 2; i * i <= n; i++) { if (n % i == 0)//质因数分解 { ll cnt = 0;//即这个因数的次方 while(n % i == 0) { ++cnt; n /= i; } ans = (ans mod) * ((cnt + 1) mod); ans = ans mod; } } if (n != 1)//说明剩下最后一个质因数 { ans *= 2; } return ans mod; }

__EOF__

本文作者Kdlyh
本文链接https://www.cnblogs.com/kdlyh/p/17873308.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   加固文明幻景  阅读(45)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下
点击右上角即可分享
微信分享提示