<1>因数、素数与合数
有很多数学题是围绕因数和素数展开的,比如求解质因数个数或和、因子数个数或和、k合因子数等等,在ACM考试中也有很大概率碰到,所以在这里列一些考试内容方便日后复习。
1.最大公约数与最小公倍数
#include<iostream> #include<cstdio> #include<cmath> using namespace std; int gcd(int x,int y){ if(x%y==0){ return y; }else{ gcd(y,x%y); } } int main() { int a,b; cin>>a>>b; int t=gcd(a,b); cout<<t<<endl; cout<<a*b/t<<endl; return 0; }
2.求素数
(1).朴素求素数
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 using namespace std; 5 int main(){ 6 int n; 7 cin>>n; 8 bool prime=true; 9 if(n==1){ 10 prime=false; 11 }else{ 12 for(int i=2;i<=sqrt(n);i++){ 13 if(n%i==0){ 14 prime=false; 15 break; 16 } 17 } 18 } 19 if(prime==false){ 20 cout<<"This is not a prime."<<endl; 21 }else{ 22 cout<<"This is a prime."<<endl; 23 } 24 return 0; 25 }
(2).线性筛素数
#include<cstdio> #include<cstring> #include<iostream> int f[1000005]; int prime[1000005]; using namespace std; int main(){ int n; scanf("%d",&n); int tot=1; f[1]=1; memset(prime,0,sizeof(prime)); for(int i=2;i<=n;i++){ if(f[i]==0){ prime[tot]=i; tot++; } for(int j=1;j<=n;j++){ if(i*prime[j]>n){ break; } f[i*prime[j]]=1; if(i%prime[j]==0){ break; } } } int sum=0; for(int i=2;i<=n;i++){ if(f[i]!=1){ sum++; cout<<i<<" "; if(sum>=10){ sum=0; cout<<endl; } } } return 0; }
(3).Miller_Rabin
1 #include<iostream> 2 #include<ctime> 3 #include<algorithm> 4 using namespace std; 5 typedef long long ll; 6 ll mul(ll a, ll b, ll m)//求a*b%m 7 { 8 ll ans = 0; 9 a %= m; 10 while(b) 11 { 12 if(b & 1)ans = (ans + a) % m; 13 b /= 2; 14 a = (a + a) % m; 15 } 16 return ans; 17 } 18 ll pow(ll a, ll b, ll m)//a^b % m 19 { 20 ll ans = 1; 21 a %= m; 22 while(b) 23 { 24 if(b & 1)ans = mul(a, ans, m); 25 b /= 2; 26 a = mul(a, a, m); 27 } 28 ans %= m; 29 return ans; 30 } 31 bool Miller_Rabin(ll n, int repeat) 32 { 33 if(n == 2 || n == 3)return true; 34 if(n % 2 == 0 || n == 1)return false; 35 ll d = n - 1; 36 int s = 0; 37 while(!(d & 1)) ++s, d >>= 1; 38 srand((unsigned)time(NULL)); 39 for(int i = 0; i < repeat; i++) 40 { 41 ll a = rand() % (n - 3) + 2; 42 ll x = pow(a, d, n); 43 ll y = 0; 44 for(int j = 0; j < s; j++) 45 { 46 y = mul(x, x, n); 47 if(y == 1 && x != 1 && x != (n - 1))return false; 48 x = y; 49 } 50 if(y != 1)return false; } 51 return true; 52 } 53 int main() 54 { 55 int T; 56 cin >> T; 57 ll n; 58 while(T--) 59 { 60 cin >> n; 61 if(Miller_Rabin(n, 50))cout<<"Yes"<<endl; 62 else cout<<"No"<<endl; 63 } 64 }
3.求质因数
(1).Pollard_rho
1 #include<iostream> 2 #include<ctime> 3 #include<algorithm> 4 #include<map> 5 using namespace std; 6 typedef long long ll; 7 map<ll, int>m; 8 const int mod = 10000019; 9 const int times = 50;//测试50次 10 ll mul(ll a, ll b, ll m) 11 //求a*b%m 12 { 13 ll ans = 0; 14 a %= m; 15 while(b) 16 { 17 if(b & 1)ans = (ans + a) % m; 18 b /= 2; 19 a = (a + a) % m; 20 } 21 return ans; 22 } 23 ll pow(ll a, ll b, ll m) 24 //a^b % m 25 { 26 ll ans = 1; 27 a %= m; 28 while(b) 29 { 30 if(b & 1)ans = mul(a, ans, m); 31 b /= 2; 32 a = mul(a, a, m); 33 } 34 ans %= m; 35 return ans; 36 } 37 bool Miller_Rabin(ll n, int repeat) 38 { 39 if(n == 2 || n == 3)return true; 40 if(n % 2 == 0 || n == 1)return false; 41 42 ll d = n - 1; 43 int s = 0; 44 while(!(d & 1)) ++s, d >>= 1; 45 for(int i = 0; i < repeat; i++) 46 { 47 ll a = rand() % (n - 3) + 2; 48 ll x = pow(a, d, n); 49 ll y = 0; 50 for(int j = 0; j < s; j++) 51 { 52 y = mul(x, x, n); 53 if(y == 1 && x != 1 && x != (n - 1))return false; 54 x = y; 55 } 56 if(y != 1)return false; 57 } 58 return true; 59 } 60 ll gcd(ll a, ll b) 61 { 62 return b == 0 ? a : gcd(b, a % b); 63 } 64 ll pollard_rho(ll n, ll c) 65 { 66 ll x = rand() % (n - 2) + 1; 67 ll y = x, i = 1, k = 2; 68 while(1) 69 { 70 i++; 71 72 x = (mul(x, x, n) + c) % n;// x = (mul(x, x, n) + c) + n; 73 ll d = gcd(abs(y - x), n);// ll d = gcd(y - x, n); 74 75 if(1 < d && d < n) 76 return d; 77 if(y == x) 78 return n; 79 if(i == k) 80 { 81 y = x; 82 k <<= 1; 83 } 84 } 85 } 86 void Find(ll n, ll c) 87 { 88 if(n == 1)return; 89 90 if(Miller_Rabin(n, times)) 91 { 92 m[n]++; 93 return; 94 } 95 96 ll p = n; 97 while(p >= n) 98 p = pollard_rho(p, c--); 99 100 Find(p, c); 101 Find(n / p, c); 102 } 103 int main() 104 { 105 ll n;srand((unsigned)time(NULL)); 106 while(cin >> n) 107 { 108 m.clear(); 109 Find(n, rand() % (n - 1) + 1); 110 cout<<n<<" = "; 111 for(map<ll ,int>::iterator it = m.begin(); it != m.end();) 112 { 113 cout<<it->first<<" ^ "<<it->second; 114 if((++it) != m.end()) 115 cout<<" * "; 116 } 117 cout<<endl; 118 } 119 return 0; 120 }
(2).线性筛
求出n以内的所有素数,再让prime[i]除n,如果能够整除,那么这个prime[i]就是n的质因数,否则不是。
4.求因数的数量
1 #include<cstdio> 2 #include<iostream> 3 using namespace std; 4 int count(int n){ 5 int s=1; 6 for(int i=2;i*i<=n;i++){ 7 if(n%i==0){ 8 int a=0; 9 while(n%i==0){ 10 n/=i; 11 a++; 12 } 13 s=s*(a+1); 14 } 15 } 16 if(n>1) s=s*2; 17 return s; 18 } 19 int main(){ 20 int n; 21 cin>>n; 22 cout<<count(n); 23 }
5.求因数的和
若一个数分解为a^x*b^y...形式,则因数和Sum计算方法为(a^0*a^1*a^2...a^x)+(b^0*b^1*b^2...b^y)+.....
浙公网安备 33010602011771号