题意:给一个数n,让你求他可以是多少组数的最小公倍数。比如12,(1,12),(2,6),(3,4)等的最小公倍数都是12
分析:本题需要用到唯一分解定理
a=p1^a1*p2^a2*p3^a3.........
b=p1^b1*p2^b2*p3^b3.........(其中pi为质因数,ai,bi为幂次)
对于他们的最小公倍数
c=p1^c1*p2^c2*p3^c3......... 其中ci=max(ai,bi);
那么在a,b中,每个因子的幂次一个等于ci,一个在0~ci之间,于是就是 cnt = 2*(k+1)个,但是ai=bi=ci的情况只有一种,并且只能固定一个幂次等于ci,一个在0~ci之间,所以应该是 cnt/2+1个
对于n的每个因子,我们都不断的对其进行整除,直到不含有这个因子。最后如果n不等于1就说明还有因子没有除尽,这时候需要在乘3,乘的是3的原因是上一段。
优化:根据唯一分解定理,每个因子都是素数,我们可以先处理一下素数,还有就是枚举的时候枚举到根号下n就好了
代码:
#include <map>
#include <set>
#include <cmath>
#include <queue>
#include <stack>
#include <cstdio>
#include <vector>
#include <iomanip>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#define ll long long
#define mod 1000000007
#define mem(a) memset(a,0,sizeof(a))
using namespace std;
typedef pair <int,int> pii;
const int maxn = 50000 + 5 , inf = 0x3f3f3f3f;
int prime[maxn];
int cnt = 0;
void isPrime(){
bool vis[maxn];
memset(vis,true,sizeof(vis));
vis[1]=false;
vis[2]=true;
memset(prime,0,sizeof(prime));
for(int i=2;i<=maxn;i++){
for(int j=i*2;j<=maxn;j+=i){
vis[j]=false;
}
}
for(int i=2;i<=maxn;i++){
if(vis[i]) prime[cnt++]=i;
}
}
int main(){
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
ll n;
isPrime();
while(scanf("%lld",&n)==1&&n){
ll ans = 1;
ll nn = n;
for(int i=0;i<=cnt&&prime[i]<=n;i++){
int k = 0;
while(n%prime[i]==0){
k++;
n/=prime[i];
}
ans*=(ll)(2*k+1);
}
if(n!=1) ans*=3;
ans/=2;ans++;
printf("%lld %lld\n",nn,ans);
}
return 0;
}