算术基本定理:一个非质数,可以分解唯一有限个质数的乘积。
N=P1^r1 * P2^r2 *P3^r3*...*Pn^rn (P1<P2<P3<...<PN & Pi 是质数 & ri>=0)
N的正因子个数为num=(a1+1)*(a2+1)........*(an+1),即为每个质数的质数+1的乘积。
核心思想:
- 对素数进行打表,将素数存在prime[]数组里。
- 对n进行分质因数解。
核心代码:
素数打表:
const int maxn=1e6+10;
int prime[maxn];
int vis[maxn],len=0;
void get_prime()
{
memset(vis,0,sizeof vis);
memset(prime,0,sizeof prime);
for(int i=2;i<sqrt(maxn);i++)
if(!vis[i])
for(int j=i*i;j<=maxn;j+=i)
vis[j]=1;
for(int i=2;i<=maxn;j+=i)
prime[len++]=i;
}
分解质因数:
void fenjie(){
for(int i=0;i<=len&&prime[i]<=sqrt(tmp);i++){
int e[maxn];
while(tmp%prime[i]==0)
{
e[i]++;
tmp/=prime[i];
}//e[i]中存放对应质数的质数,prime[i]存放质数
}
}
例题:LightOJ Aladdin and the Flying Carpet 1341
题意:阿拉丁有个长方形魔法毯子,a代表着毯子的面积,在固定面积情况下,毯子可以有很多形状,长宽的组合不同,规定边最小是b。
解题思路:这道题利用算法基本定理的应用,一个非质数的正因数等于每个质因数指数的+1的乘积(开头说过了)。因此,这道题的思路就是求解出质因数的指数,计算出n共有多少对正因子n,然后再减去1到b范围内的质因子个数,得出所求结果。
算出的质因子个数num要除二,因为是质因子是两两成对的。
AC代码如下:
#include<bits/stdc++.h>
using namespace std;
long long const maxn=1e6+13;
typedef long long ll;
ll a,b,tmp,num,k=0,len,e;
ll primes[maxn];
int vis[maxn];
void get_primes()//素数打表,得到n内所有素数
{
memset(primes,0,sizeof primes);
memset(vis,0,sizeof vis);
for(int i=2;i<=sqrt(maxn);i++)
if(!vis[i])
for(int j=i*i;j<=maxn;j+=i)
vis[j]=1;
for(int i=2;i<=maxn;i++)
if(!vis[i])
primes[len++]=i;
}
void fenjie()
{ //分解因子
for(int i=0;i<len&&primes[i]<=sqrt(tmp);i++)
{ int e=0;
while(tmp%primes[i]==0)
{
tmp/=primes[i];
e++;
}
num*=(e+1);
}
if(tmp>1)//如果tmp为非0.则a还有一个素数质因子
num*=2;
}
int main(){
int t;
cin>>t;
get_primes();
while(t--)
{
cin>>a>>b;
if(b>=sqrt(a))
{ num=0;
printf("Case %d: %d\n",++k,num);
continue;
}
else
{ num=1;
tmp=a;
fenjie();
num/=2;
for(int i=1;i<b;i++)
{ //减去b以内因数个数
if(a%i==0)
num--;
}
printf("Case %d: %d\n",++k,num);
}
}
return 0;
}
如有错误或者疑问,欢迎指出~