试除法求约数:
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
int n;
void get_divisors(int n)
{
vector<int> res;
for (int i = 1; i <= n / i; i++)//如果i是n的约数,则n/i==x(x肯定是整数),那么n/x==i(i是整数(因为i是约数))。
{ //说明i若是n的约数,则n/i也是n的约数,因此只要判断<n/i的部分就行,在判断约数的时候直接怕n/i也放入答案
if (n % i == 0)//如果i是n的约数
{
res.push_back(i);
//如果i是n的约数,那么n/i也是n的约数
if (i != n / i) res.push_back(n / i);// 避免 i==n/i, 重复放入
}
}
sort(res.begin(), res.end());
for (auto item : res) {
printf("%d ",item);
}
printf("\n");
}
int main()
{
scanf("%d",&n);
while (n--)
{
int x;
scanf("%d",&x);
get_divisors(x);
}
return 0;
}
约数个数:
#include<iostream>
#include<unordered_map>
using namespace std;
typedef long long LL;
const int mod = 1e9 + 7;
int main()
{
int n,x;
LL ans = 1;//答案先为1,因为后面是用乘法算的,所以不能为0
unordered_map<int,int> hash;//纪录某个数的指数,first存数字,second存指数
scanf("%d",&n);
while(n--)
{
scanf("%d",&x);
//如果i是x的约数,那么x/i也是x的约数,那么x就可以化成更小的了。如8的约数是2,4,8,那么当i=2时,就可以把8化成4了,在化×成2,这样就是2*2*2,。这样就不会算成2*4而是2*2*2
//是因为做法要求的是尽量约数要小,指数要大,所以x的约数一定比x/i小,一旦比x/i大了,那说明该数没有约数了,就进行下面的if(x>1)语句
//质因数从2开始
for(int i = 2;i <= x/i; ++i)
{
while(x % i == 0)
{
x /= i;
hash[i] ++;
}
}
if(x > 1) hash[x] ++;//x的最大公约数可能大于sqrt(x),要特别考虑
}
//将统计出来的数按照由图中公式所得出来的结论得出答案
for(auto i : hash) ans = ans*(i.second + 1) % mod;//%mod是防止整型溢出
//如案例:2*6*8的约数个数,2的约数为2;6的约数为2、3;8的约数为2、2、2,所以2的指数为5,3的指数为1,由公式得:(5+1)*(1+1)=12
printf("%d\n",ans);
return 0;
}
约数之和:
注意:a不仅是质数,而且必须是质因数
#include <iostream>
#include <unordered_map>
using namespace std;
typedef long long LL;
const int N = 110, mod = 1e9 + 7;
int main()
{
int n;
scanf("%d",&n);
unordered_map<int, int> primes;//纪录某个数的指数,first存数字,second存指数
while (n -- )
{
int x;
scanf("%d",&x);
//如果i是x的约数,那么x/i也是x的约数,那么x就可以化成更小的了。如8的约数是2,4,8,那么当i=2时,就可以把8化成4了,在化×成2,这样就是2*2*2,。这样就不会算成2*4而是2*2*2
//是因为做法要求的是尽量约数要小,指数要大,所以x的约数一定比x/i小,一旦比x/i大了,那说明该数没有约数了,就进行下面的if(x>1)语句
//质因数从2开始
for (int i = 2; i <= x / i; i ++ )
while (x % i == 0)
{
x /= i;
primes[i] ++ ;
}
if (x > 1) primes[x] ++ ;//x的最大公约数可能大于sqrt(x),要特别考虑
}
LL res = 1;
for (auto p : primes)
{
LL a = p.first, b = p.second;
LL t = 1;
//将统计出来的数按照由图中公式所得出来的结论得出答案
while (b -- ) t = (t * a + 1) % mod;//%mod是防止整型溢出,该处用的公式在下面注释写了过程
res = res * t % mod;
//如案例:2*6*8的约数之和,2的约数为2;6的约数为2、3;8的约数为2、2、2,所以2的指数为5,3的指数为1
//由公式得:t=1*2+1=3,t=3*2+1=7,t=7*2+1=15,t=15*2+1=31,t=31*2+1=63,res=1*63=63。2的5次方就是63
// t=1*3+1=4,res=63*4=252
}
printf("%d\n",res);
return 0;
}
最大公约数:
#include<iostream>
using namespace std;
int gcd(int a, int b)
{
if(a % b == 0)return b;
return gcd(b,a % b);//这里不用看a和b谁大,因为递归还是会反过来比较,如a比b小,则递归后a%b==a,又是b在前面a在后面
//例二:4和6的最大公约数
//a=6 4
//b=4 2,此时余数为0返回b
}
int main()
{
int n,a,b;
scanf("%d",&n);
while(n--)
{
scanf("%d%d",&a,&b);
printf("%d\n",gcd(a,b));
}
return 0;
}