题目链接:https://vjudge.net/problem/LightOJ-1236
解题思路:
如果LCM(a,b) = n
那么有如下结论:
对n进行质因子分解,pi表示n的质因子,ei表示pi的次数
n = p1^e1 * p2^e2...... * pn^en
那么对应a,b质因子分解,用ai,bi表示a,b对应质因子的次数
a = p1^a1 * p2^a2...... * pn^an
b = p1^b1 * p2^b2...... * pn^bn
对应e1 = max(a1,b1),e2 = max(a2,b2)......en = max(an,bn)
因此我们只需求出n所有质因子,以及质因子的次数。
那么ai,bi两个数只要一个取ei,另一个可以取0~ei,那么(ei+1)×2,其中ei,ei这组重复,所以总共 2×ei+1 对不同的
我们算出 ,这样求出来是所有的对数,而我们需要的是b>=a的对数,算出的所有方法中只有有一种
情况是是a=b,就是每一对(ai,bi)都取ei,也就是每一对都相等,最后a,b才相同。因此总方法数有三种情况组成:
a>b + a<b + 特殊情况a=b
复杂度:O(sqrt(N))预处理2~sqrt(N)的素数,每次O(logN)质因子分解
O(sqrt(N)+ q*logN)
///本题结论:两个数的LCM的一种求法:各自质因子分解,取最每个质因子两边的较大系数就是LCM
///gcd就是都取较小值
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define ll long long
#define for0(i,a,b) for (ll i=a;i<b;i++)
#define for1(i,a,b) for (ll i=a;i<=b;i++)
const int N = 1e7;
int prime[700000],tot;
bool vis[N+5];
void euler()
{
tot = 0;
for1(i,2,N){
if (!vis[i]){
prime[tot++] = i;
}
for (int j=0;j<tot&&i*prime[j]<=N;j++){
vis[i*prime[j]] = true;
if (i%prime[j]==0) break;
}
}
//printf("tot=%d\n",tot);
}
bool leave;///是否可以被1e7的质数分解完
int cnt[700000];///1e7质数的大概数量
int main()
{
euler();
int T,ica=1;
scanf("%d",&T);
while (T--){
leave = false;
memset(cnt,0,sizeof cnt);
ll n;
scanf("%lld",&n);
int now = 0;
while (n!=1){
if (now==tot) break;
if (n%prime[now]==0) n/=prime[now],cnt[now]++;
else now++;
}
if (n!=1) leave = true; ///没有用sqrt(N)内的质数分解完,剩余部分就是质数,且次数为1,总方法数*3
ll ans = 1;
for0(i,0,700000){
if (cnt[i]) ans = ans*(2*cnt[i]+1);//,printf("cnt[%d]=%d\n",prime[i],cnt[i]);
}
if (leave) ans = ans*3; ///01,10,11
printf("Case %d: %lld\n",ica++,(ans+1)/2);
}
return 0;
}