一 质数
1.试除法判定质数:
bool is_prime(int n)//试除法判定质数
{
if(n<2) return false;
for(int i=2;i<=n/i;i++)
{
if(n%i==0) return false;
}
return true;
}
2.试除法分解质因数:
void divide(int n)//试除法分解质因数
{
for(int i=2;i<=n/i;i++)
{
if(n%i==0)
{
int s=0;//s表示质因数i的次数
while(n%i==0)
{
n/=i;
s++;
}
cout<<i<<' '<<s<<endl;//输出质因数i及它的次数
}
}
if(n>1) cout<<n<<' '<<1<<endl;//由于n中最多只包含一个大于根号n的质因子
}
3.无限循环分解质因数:
void divide(int n)//无线循环分解质因数
{
for(int i=2;i>=0;)
{
if(n%i==0)//说明i是n的一个质因子
{
cout<<i<<' ';//将该质因子输出
while(n%i==0) n/=i;//将质因子i处理干净
if(n==1) break;//当n为1时,分解完成
}
else i++;
}
cout<<endl;
}
4. 埃氏筛法求质数:
求素数最快的方法:埃氏筛法
/*思想: 首先将2到n范围内的整数写下来,很明显,2是最小的素数,将表中所有是2的倍数的数都划去,然后表中最小的数字是3,则3就是素数,然后再将表中所有是3的倍数的数都划去,以此类推…;
可以用一个标志数组,将划去的数标记为true,用一个数组来存放2到n范围内的所有素数;
代码实例:
#include<iostream>
#include<vector>
#include<set>
#include<stack>
#include<queue>
#include<algorithm>
#include<string>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<ctype.h>
using namespace std;
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
typedef long long ll;
const int N = 2e6 + 10;
int a[N];//用来存放所有素数
int q;//用来记录素数的个数
int i,j;//全局变量,避免多次定义,可以减少运行时间
bool vis[2000000];//标记数组
int main()
{
for ( i = 2; i <= 2000000; i++)
{
if (!vis[i])//如果为false,说明没有被划去,为素数
{
for (j = 2; i * j <= 2000000; j++)//将区间内所有的数都划去
{
vis[i * j] = true;//将所有是素数i的倍数的数都划去,标记true;
}
a[q++] = i;//把该素数存到数组中
}
}
int m, n;
while (cin>>m>>n)//在此处可以把cin和cout换掉,可以减少程序运行时间
{
int ans = 0;
for (i = 0; i < q; i++)
{
if (a[i] >= m && a[i] <= n)
{
ans++;
}
if (a[i] > n) break;
}
cout << ans << endl;
}
return 0;
}
二 约数
1.试除法求一个数的所有约数:
vector<int> get_yue(int n)//求约数,按照从小到大顺序输出
{
vector<int> res;
for(int i=1;i<=n/i;i++)
{
if(n%i==0)
{
res.push_back(i);
if(i!=n/i) res.push_back(n/i);
}
}
sort(res.begin(),res.end());
for(auto i:res) cout<<i<<' ';
cout<<endl;
return res;
}
2.求约数个数:
求n个数的乘积之后的因数个数:
思想:将每个数分解质因子,n个数乘积之后的因数个数就等于每个数的所有质因子的次数加一的乘积。
unordered_map<int,int> has;//此容器是把key和value关联起来的容器,
//可以高效地根据key值查找对应的value值,其内部实现了哈希表。
代码实例:
输入:
3
2 6 8
输出:12
#include<iostream>
#include<algorithm>
#include<iostream>
#include<algorithm>
#include<vector>
#include<set>
#include<stack>
#include<queue>
#include<string>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<ctype.h>
#include<iomanip>
#include<unordered_map>
#include<fstream>
using namespace std;
#define endl '\n'
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
typedef unsigned long long ULL;
typedef pair<int, int> PII;
typedef long long ll;
const int N = 2e5 + 10, null = 0x3f3f3f3f,M=2*N;
const int mod=1e9+7;
int n;
unordered_map<int,int> has;
int main()
{
ios;
cin>>n;
while(n--)
{
int x;
cin>>x;
for(int i=2;i<=x/i;i++)
{
if(x%i==0)
{
while(x%i==0)
{
x/=i;
has[i]++;
}
}
}
if(x>1) has[x]++;
}
ll ans=1;
for(auto i:has) ans=ans*(i.second+1)%mod;//求出所有质因子的个数加一的乘积
cout<<ans<<endl;
return 0;
}
3.求约数之和:
#include<iostream>
#include<algorithm>
#include<iostream>
#include<algorithm>
#include<vector>
#include<set>
#include<stack>
#include<queue>
#include<string>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<ctype.h>
#include<iomanip>
#include<unordered_map>
#include<fstream>
using namespace std;
#define endl '\n'
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
typedef unsigned long long ULL;
typedef pair<int, int> PII;
typedef long long ll;
const int N = 2e5 + 10, null = 0x3f3f3f3f,M=2*N;
const int mod=1e9+7;
int n;
unordered_map<int,int> has;
int main()
{
ios;
cin>>n;
while(n--)
{
int x;
cin>>x;
for(int i=2;i<=x/i;i++)
{
if(x%i==0)
{
while(x%i==0)
{
x/=i;
has[i]++;
}
}
}
if(x>1) has[x]++;
}
ll ans=1;
for(auto i:has)
{
int x=i.first;
int y=i.second;
ll t=1;
while(y--)
{
t=(t*x+1)%mod;
}
ans=ans*t%mod;
}
cout<<ans<<endl;
return 0;
}
4.求最大公因数:
辗转相除法求最大公因数:
int gcd(int a,int b)
{
return b?gcd(b,a%b):a;
}
int gcd(int a,int b)
{
if(b==0) return a;
else return gcd(b,a%b);
}
int gcd(int a,int b)
{
while(b)
{
int t=a%b;
a=b;
b=t;
}
return a;
}
最大公因数与最小公倍数的乘积等于两个数的乘积。
小技巧:已知两个数以及两个数的最大公因数,求最小公倍数的方法:先将这两个数的一个数除以最大公因数,再乘以另一个数,即先除再乘。此方法可以避免出现类型溢出,防止爆int。