1.试除法求所有约数
题面:
代码:
#include<bits/stdc++.h>
#include<vector>
using namespace std;
typedef long long ll;
vector<int> getdivisors(int n)//用容器来存
{
vector<int>res;
/*由于n/d=x,同时n/x=d也成立,所以可以得出约数是成对存在的。
由此我们只需要枚举一下较小的的那个,即d<=n/d,把循环条件写成i<=n/i,这样时间复杂度就为O(sqrt(n))了。
*/
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);//这里特判一下,如2*2=4,避免存入了两个2
}
}
sort(res.begin(),res.end());//从小到大排序一下
return res;
}
int main()
{
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
auto res=getdivisors(n);
for(auto t:res) cout<<t<<" ";
cout<<endl;
}
return 0;
}
2.约数个数
由算数基本定理可得,任何一个数可以用如下式子表示,其中Pi是质因数,ai为指数。
约数个数也可表示出来:
X=(a1+1)* (a2+1)*(a3+1)*…*(ak+1)
分析:
n的任意一个约数d,也有如下式子表示
其中0<=bi<=ai。
由于n的所有约数都可以用上式表示,且不同的Bi对应不同的约数,所以P1可以分为(a1+1)种,【(a1+1)即为0,1,2,…,a1】P2可以分为(a2+1)种…Pk可以分为(ak+1)种。综上述,约数个数为:(a1+1)* (a2+1)*(a3+1)*…*(ak+1)。
题目链接:870. 约数个数 - AcWing题库
题面:
代码(思路见注释):
#include<bits/stdc++.h>
#include<map>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;//有t个数
cin>>t;
unordered_map<int,int>primes;//用哈希表来存每个数分解出来的质因数的个数
while(t--)//依次输入t个数
{
ll n;
cin>>n;
for(int i=2;i<=n/i;i++)//求质因数
{
while(n%i==0)//得到此质因数的指数
{
n/=i;
primes[i]++;
}
}
if(n>1) primes[n]++;//存在唯一一个大于sqrt(n)的质因子
}
ll ans=1;
//遍历一遍所有质因子,约数个数就用指数+1累乘
for(auto prime:primes) ans=ans*(prime.second+1)%mod;
cout<<ans<<endl;
return 0;
}
3.约数之和
由算数基本定理可得,任何一个数可以用如下式子表示,其中Pi是质因数,ai为指数。
约数之和表示为:
这里就不解释了,理解一下啦。
题目链接:871. 约数之和 - AcWing题库
题面:
代码(思路见注释):
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;//有t个数
cin>>t;
unordered_map<int,int>primes;//用哈希表来存每个数分解出来的质因数的个数
while(t--)//依次输入t个数
{
ll n;
cin>>n;
for(int i=2;i<=n/i;i++)//求质因数
{
while(n%i==0)//得到此质因数的指数
{
n/=i;
primes[i]++;
}
}
if(n>1) primes[n]++;//存在唯一一个大于sqrt(n)的质因子
}
ll ans=1;
//遍历一遍所有质因子,约数之和就如公式表示
for(auto prime:primes)
{
int p=prime.first,a=prime.second;
//表示其中一个质因数,b表示质因数的指数为多大
ll t=1;
while(a--)//依次计算pi的0次方+pi的1次方+...+pi的ai次方
{
t=(t*p+1)%mod;
}
ans=ans*t%mod;
}
cout<<ans<<endl;
return 0;
}
这里提一下:
4.最大公约数
前提:若d能整除a,且d能整除b,则d能整除(a+b),且d能整除a、b的任意倍数之和(a*x+b*y)。
则有gcd(a,b)=gcd(b,a mod b)。[gcd为求最大公约数的函数,mod为取模]
证明:a mod b=a-c*b (c为a/b)
若有d/a,d/b,则有d/(a+(-c)*b),所以等式两边的集合相同,即公约数相同。
题面:
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
ll n,a,b;
ll gcd(ll a,ll b)
{
return b?gcd(b,a%b):a;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n;
while(n--)
{
cin>>a>>b;
cout<<gcd(a,b)<<endl;
}
return 0;
}