题目大意:
给你一个 n,请你找出共有多少对(i,j)满足 lcm(i,j) = n (i<=j) 。
解题思路:
我们利用算术基本定理将 n,i,j 进行分解:
n = P1a1 * P2a2 * ... * Pnan
i = P1b1 * P2b2 * ... * Pnbn
j = P1c1 * P2c2 * ... * Pncn
我们以 P1 项为例。因为 lcm(i,j) = n,故我们不难推知 0<= b1,c1 <=a1,且 b1 和 c1 之中必有一个等于 a1(读者可以试想一下:如果 b1 和 c1 都小于 a1,那么 i 和 j 的最小公倍数分解下来又怎么会有一个 P1a1 呢?)。于是我们不难得出 b1 和 c1 的搭配数为:2*(a1+1) - 1,总对数为:([2*(a1+1) - 1][2*(a2+1) - 1] ... [2*(an+1) - 1] + 1)/2.
Have a good day.
AC代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <cmath> 4 #include <cstring> 5 6 using namespace std; 7 typedef long long ll; 8 const ll maxn=1e7+3; 9 bool be_prim[maxn]; 10 ll prim[664579]; 11 int cnt; 12 void init(){ 13 cnt=0; 14 memset(be_prim,true,sizeof(be_prim)); 15 be_prim[0]=be_prim[1]=false; 16 for(ll i=2;i<maxn;i++){ 17 if(be_prim[i]){ 18 prim[cnt++]=i; 19 for(ll j=i*i;j<maxn;j+=i){ 20 be_prim[j]=false; 21 } 22 } 23 } 24 } 25 int main() 26 { 27 init(); 28 int T, ta; 29 ll n, ans; 30 scanf("%d",&T); 31 for(int t=1;t<=T;t++){ 32 ans=1; 33 scanf("%lld",&n); 34 printf("Case %d: ",t); 35 for(int i=0;i<cnt;i++){ 36 if(n%prim[i]==0){ 37 ta=1; n/=prim[i]; 38 while(n%prim[i]==0){ 39 ta++; 40 n/=prim[i]; 41 } 42 ans*=(2*(ta+1)-1); 43 } 44 if(n==1) break; 45 } 46 if(n>1) ans*=3; 47 printf("%lld ",(ans+1)/2); 48 } 49 return 0; 50 }