一、题目链接:传送门
二、题解: <1> 先对n进行素因子分解,时间复杂度近似sqrt(n) / k,k为一个常数。
<2> 假设 n = a1^p1 * a2 ^ p2 * a3 ^ p3 * ... * an ^ pn。 (ai为素因子,pi为素因子的指数)
<3> 假设Lcm(a,b) = n,则对于每一个素因子ai,a中的pi,与b中的pi,至少有一个为ai的指数。
<4> 所以对于n中的每一个素因子的指数c,我们都可以分解成一对(a,b),且max(a,b) = c,这样的分法有2 * c + 1中,
对于其它的素因子同理,因为Lcm对是有序的,所以最后的结果要除以2,再加1,因为(n,n)我们只算了一次。
三、AC代码如下:
/* ***********************************************
Author :xdlove
Created Time :2015年09月03日 星期四 13时02分46秒
File Name :a.cpp
************************************************ */
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <memory.h>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
typedef long long ll;
const int MAXN = 1e7;
bool check[MAXN + 2];
int prime[700000];
int e[700000];
void getprime()
{
memset(check,false,sizeof(check));
for(int i = 2; i <= MAXN; i++)
{
if(!check[i]) prime[++prime[0]] = i;
for(int j = 1; j <= prime[0]; j++)
{
if(prime[j] > MAXN / i) break;
check[i * prime[j]] = true;
if(i % prime[j] == 0) break;
}
}
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
//srand(time(NULL));
getprime();
int T,cnt = 0;
ll n;
cin>>T;
while(T--)
{
scanf("%lld",&n);
memset(e,0,sizeof(e));
for(int i = 1; i <= prime[0]; i++)
{
if(prime[i] > n / prime[i]) break;
while(n % prime[i] == 0)
{
e[i]++;
n /= prime[i];
}
if(n == 1) break;
}
ll ans = 1;
for(int i = 1; i <= prime[0]; i++)
if(e[i]) ans *= 2 * e[i] + 1;
if(n != 1) ans *= 3;
printf("Case %d: %lld\n",++cnt,ans/2 + 1);
}
return 0;
}