试除法求约数
这里可以考虑用set容器,因为set容器是不允许重复的元素出现的 试除法 就是到了i<=n/i的if(x%i==0)ans.insert(i),ans.insert(n/i)就算是他们重复 set容器也是直接忽略了
而且set容器还是有clear的功能的
约数的个数
N=p1^a1*p2^a2*p3^a3…….
那么约数的个数就是ans=(a1+1)*(a2+1)*(a3+1)*……
a1有a1中情况 p1的指数不同 那么N的约数就不同 因此会有a1+1中形式 因为还有1呢
约数的个数 还可以返回set的size这个操作
代码附上:
for(int i = 1; i <= x / i; ++i) {
ret.insert(i);
ret.insert(x / i);
}
cout << "约数的个数是: " << ret.size() << '\n';
代码附上:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod = 1e9 + 7;
unordered_map<int, int>Hash;
signed main() {
int x;
cin >> x;
for(int i = 2; i <= x / i; ++i) {
while(x % i == 0) {
x /= i;
Hash[i]++;
}
}
if(x > 1)Hash[x]++;//这个要注意
int ret = 1;
for(auto i : Hash) {
ret = ret * (i.second + 1) % mod;
}
cout << ret << endl;
return 0;
}
约数的和
约数的和也是和N=p1^a1*p2^a2*p3^a3…..这有关系的
ans=(p1^0+p1^1+p1^2+….p1^a1)*(p2^1+p2^2+p2^3+…..p2^a2)*……….
这里也是有技巧的
这里a是底数 b是指数while(b--)进行b次操作 t=(t*a+1)
第一次是t=1 第二次t=(a+1)第三次t=(a+1)*a+1就变成a^2+a+1是不是很神奇
-
最大公约数
辗转相除的原理 其实也是直接可以调用系统函数__gcd 前面是有两个下划线的
最小公倍数直接就是 a*b/__gcd(a,b)就是最小公倍数
但是java里面没有 怎么去写呢?
代码:
后来发现java里面也有自带的求gcd的方法 不过在BigInteger里面 BigInteger的valueof可以进行类型之间的转换 java里面一般用的是long 就可以表示很大的数了
约数的个数的例题:
- 分析:
数学公式的推导和约数的个数的应用
- 代码:
void init(int n) { for(int i = 2; i <= n; ++ i ) { if(st[i] == false)primes[++cnt] = i; for(int j = 1; primes[j] <= n / i; ++ j ) { st[i * primes[j]] = true; if(i % primes[j] == 0)break; } } } signed main() { IOS; init(1000000); int n, ret = 1; cin >> n; //题目的间接的意思 就是让咱们求 n^2 的阶乘约数的个数 for(int i = 2; i <= n; ++ i ) {//枚举的是质数 int x = i, t = 0; if(st[i] == true)continue; while(x <= n) {//看看n的阶乘里面可以分解多少个X t += n / x; x = x * i; } ret = ret * (1 + 2 * t) % mod; } cout << ret << endl; return 0; }
-
反素数(例题):
- 分析:
这个题是dfs 和想不到的贪心和数学推导
- 代码:
void dfs(int len, int last, int p, int sum ) {//质数数组的长度 上一次用的个数 记录的这个数值 当前约数的个数 if(sum > Max || (sum == Max && p < ret)) { ret = p, Max = sum; } if(len == 8 + 1) { return ; } for(int i = 1; i <= last; ++ i ) { p = p * primes[len];//继承 if(p <= n) { dfs(len + 1, i, p, sum * (1 + i)); } else return; } } signed main() { IOS; cin >> n; dfs(0, 30, 1, 1); cout << ret << endl; return 0; }
-
例题:
题目的大概意思是 给你四个数
a b c d
让你求有多少满足条件的
gcd(x, a) = b
lcm(x, c) = d
分析:
由lcm(x, c) = d 可以知道x是d的因数 因此可以去枚举d的所有因数 看看有哪些满足条件的
- 代码:
但是这样的算法不是很完美
分析2:
lcm 枚举质因数 然后暴搜
牛客小白月赛81
C-陶陶学算术_牛客小白月赛81 (nowcoder.com)
java会超时
用的是大整数会超时 后期补一下