LightOJ1236

题目大意:

  给你一个 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\n",(ans+1)/2);
48     }
49     return 0;
50 }

 

posted @ 2017-10-23 16:05  Blogggggg  阅读(145)  评论(0编辑  收藏  举报