<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;
}
View Code

 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 } 
View Code

(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;
}
View Code

(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 }
View Code

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 }
View Code

(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 }
View Code

5.求因数的和

若一个数分解为a^x*b^y...形式,则因数和Sum计算方法为(a^0*a^1*a^2...a^x)+(b^0*b^1*b^2...b^y)+.....

 

posted on 2020-02-09 20:24  海木言华  阅读(269)  评论(0)    收藏  举报