LightOJ 1341 唯一分解定理

Aladdin and the Flying Carpet
Time Limit:3000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu
Appoint description: 

Description

It's said that Aladdin had to solve seven mysteries before getting the Magical Lamp which summons a powerful Genie. Here we are concerned about the first mystery.

Aladdin was about to enter to a magical cave, led by the evil sorcerer who disguised himself as Aladdin's uncle, found a strange magical flying carpet at the entrance. There were some strange creatures guarding the entrance of the cave. Aladdin could run, but he knew that there was a high chance of getting caught. So, he decided to use the magical flying carpet. The carpet was rectangular shaped, but not square shaped. Aladdin took the carpet and with the help of it he passed the entrance.

Now you are given the area of the carpet and the length of the minimum possible side of the carpet, your task is to find how many types of carpets are possible. For example, the area of the carpet 12, and the minimum possible side of the carpet is 2, then there can be two types of carpets and their sides are: {2, 6} and {3, 4}.

Input

Input starts with an integer T (≤ 4000), denoting the number of test cases.

Each case starts with a line containing two integers: ab(1 ≤ b ≤ a ≤ 1012) where a denotes the area of the carpet and b denotes the minimum possible side of the carpet.

Output

For each case, print the case number and the number of possible carpets.

Sample Input

2

10 2

12 2

Sample Output

Case 1: 1

Case 2: 2

 

1.有多少个约数:

先分解质因数
因数的次数分别是4,2,1

所以约数的个数为(4+1)*(2+1)*(1+1)=5*3*2=30个

eg:

先分解质因数

720=24*32*51

因数的次数分别是4,2,1

所以约数的个数为(4+1)*(2+1)*(1+1)=5*3*2=30个

 

2.所有约数之和:

2004的约数之和为:1, 2, 3, 4, 6, 12, 167, 334, 501, 668, 1002 ,2004  = 4704

如何求一个数所有约数之和呢?

首先,应用算术基本定理,化简为素数方幂的乘积。

X = a1^k1 * a2^k2........an^kn

X的所有素数之和可用公式(1+a1 + a1^2...a1^k1) * (1+a2 + a2^2...a2^k2) * .....(1+an + an^2...an^kn)表示

如:

2004 = 2^2  * 3  *167

2004所有因子之和为(1  + 2 + 2^2) * (1 + 3) * ( 1 + 167) = 4704;

程序实现的时候,可利用等比数列快速求1 + a1 + a1^2 + .....a1^n;

思路:

求出它的每个质因子的个数,然后用公式求出它的约数个数。如果b * b > a,那么值一定为0,其余部分可以枚举b,删除。但是我觉得枚举应该会挂掉,

但是竟然没有挂。。

 

/*
 * Author:  sweat122
 * Created Time:  2016/7/11 14:53:29
 * File Name: main.cpp
 */
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<string>
#include<vector>
#include<cstdio>
#include<time.h>
#include<cstring>
#include<iostream>
#include<algorithm>
#define INF 1<<30
#define MOD 1000000007
#define ll long long
#define lson l,m,rt<<1
#define key_value ch[ch[root][1]][0]
#define rson m+1,r,rt<<1|1
#define pi acos(-1.0)
using namespace std;
const int MAXN = 1000050;
int notprime[MAXN],prime[MAXN],cnt;
ll a,b;
void init(){
    cnt = 0;
    memset(prime,0,sizeof(prime));
    memset(notprime,0,sizeof(notprime));
    for(int i = 2; i < MAXN - 50; i++){
        if(!notprime[i]){
            prime[cnt++] = i;
        }
        for(int j = 0; j < cnt && 1LL * prime[j] * i < MAXN - 50; j++){
            notprime[prime[j] * i] = 1;
            if(i % prime[j] == 0) break;  
        }
    }
}
int main(){
    int t,Case = 0;
    init();
    scanf("%d",&t);
    while(t--){
        scanf("%lld%lld",&a,&b);
        ll ans = 1;
        ll x = a;
        for(int i = 0; i < cnt; i++){
            if(prime[i] > x)break;
            if(x % prime[i] == 0){
                int num = 0;
                while(x % prime[i] == 0){
                    num += 1;
                    x /= prime[i];
                }
                ans *= (num + 1);
            }
        }       
        if(x > 1) ans *= (1 + 1);
        ans /= 2;
        if(b * b > a){
            printf("Case %d: %lld\n",++Case,0);
        } else{
            for(int i = 1; i < b; i++){
                if(a % i == 0) ans -= 1;
            }   
            printf("Case %d: %lld\n",++Case,ans);
        }
    }
    return 0;
}

 

posted @ 2016-07-11 16:12  sweat123  阅读(1022)  评论(0编辑  收藏  举报