题面:
给定一个数n求两个数a,b满足lcm(a,b)==n,且1≤a≤b≤n。问a,b个数。
数据范围n≤10^14,最多有200个n。
这是一道明显的数论题。
虽然一直是希望同学们能够打表找规律,依照规律出正解。但本人找规律和打表能力都极差,只能依靠手动推导侥幸骗分。不幸的是上午智商下线,混充暴力获得三十分。
下面给出不严谨证明(有一点跳跃和辣眼睛):
首先还是分解质因数。将n分解成n=Πpi ei n=Πpiei的形式。可以证明a和b不能有除此之外的任何素数,不然lcm(a,b)必定不等于n。其次我们将a,b分解a=Πpi ai a=Πpiai和b=Πpi bi b=Πpibi。再次可以证明的是∀ei,ei=max(ai,bi) ∀ei,ei=max(ai,bi)。既然是这样就很好搞了,先不管a和b谁大谁小。对于每一个pi,有ai=ei或者bi=ei。假设ai=ei,则bi可以是0~ei中的任何数,有(ei+1)中可能;同理对于bi=ei也有(ei+1)种可能,但要删去重复情况(ei,ei)(出现两次)。所以对于每个ei我们有(2*ei+1)种可能。将所有情况乘起来,再加上只算了一次的(a=n&&b=n),除以二就是正确答案。
我果然很笨。。。。
code:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
const LL N=7e6;
const LL np=20;
LL fac[N+1000],p[N>>3];
LL cnt=0;
LL a[np],tot,ans;
int main(){
freopen("fun.in","r",stdin);
freopen("fun.out","w",stdout);
for(int i=2;i<=N;i++){
if(!fac[i]) fac[i]=i,p[++cnt]=i;
for(int j=1;j<=cnt&&p[j]<=fac[i];j++){
if(i*p[j]>N) break;
fac[i*p[j]]=p[j];
}
}
long long T,kase=0,n,x;
cin>>T;
while(T--){
scanf("%lld",&n);
memset(a,0,sizeof(a));
tot=0,ans=0,x=n;
for(int j=1;j<=cnt;j++){
if(p[j]*p[j]>x) break;
if(x%p[j]==0){
tot++;
while(x%p[j]==0){
x/=p[j];
a[tot]++;
}
}
}
if(x!=1) a[++tot]=1;
ans=a[1]*2+1;
for(int i=2;i<=tot;i++){
ans=ans*(2*a[i]+1);
}
ans=ans+1>>1;
printf("Case %lld: ",++kase);
cout<<ans<<endl;
}
return 0;
}