数论
搬运自好友:therainisme的博客
试除法判定质数
就从2开始除,如果不能被整除就继续除,直到n为止,也就是说,直到i∗i≤n为止
1 2 3 4 5 6 7 8 9
| bool check(int x){ if(x < 2) return false; else{ for(int i =2;i<= x/i;i++){ if(x%i==0) return false; } } return true; }
|
分解质因素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| void divide(int x) { for (int i = 2; i <= x / i; ++i) { if (x % i == 0) { int cnt = 0; while (x % i == 0) { cnt++; x /= i; } cout << i << " " << cnt << endl; } } if (x > 1) cout << x << " " << 1 << endl; }
|
试除法求所有因数
1 2 3 4 5 6 7 8 9 10 11 12 13
| vector<int> v; void divide(int x){ for(int i =1;i<=x/i;i++){ if(x%i == 0){ v.push_back(i); if(x/i != i) v.push_back(x/i); } } sort(v.begin(),v.end()); }
|
约数个数
本质就是对质因数的不同指数形式的全排列
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| map<int,int>cnt; map<int,int>::iterator it;
void divide_sum(long long x){ for(long long i = 2;i<=x/i;i++){ while(x%i==0){ cnt[i]++; x/=i; } } if(x>1)cnt[x]++; }
long long get_res(){ long long res = 1; for(it = cnt.begin();it != cnt.end();it++){ res = res*(it->second+1)%MOD; } return res; }
|
约数之和
本质上可以利用质因素进行计算求和结果T,如下公式会比较清晰,a1,a2,...,an表示不同的质因数
T=(a10+a12+...+a1k)×(a20+a22+...+a2k)×...×(an0+an2+...+ank)
举个栗子,该栗子可以用于求解每一个括号中的内容:
T=1+21+22+23=1+2×(1+21+22)=1+2×(1+2×(1+2))
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
|
long long get_res(){ long long res = 1; for(it = cnt.begin();it != cnt.end();it++){ int p = it->first; int e = it->second; long long t = 1; while(e--)t = (t*p+1) % MOD; res = res *t %MOD; } return res; }
int qmi(int a,int k){ int res = 1; a%=mod; while(k){ if(k&1)res = res*a%mod; a=a*a%mod; k>>=1; } }
int sum(int a,int k){ if(k==0)return 1; if(k%2==0)return (1+a%mod*sum(a,k-1))%mod; return (1+qmi(a,k/2+1))*sum(a,k/2)%mod; }
|
最大公约数和最小公倍数
gcd(a,b)求的是最大公约数,
a*b/gcd(a,b)求的是最小公倍数
本质是辗转相除法的递归写法
1个字,妙啊
1 2 3
| int gcd(int a,int b){ return b?gcd(b,a%b):a; }
|