lightoj 1341 算术基本定理


1341 - Aladdin and the Flying Carpet
Time Limit: 3 second(s)Memory Limit: 32 MB

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

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

Now you are given the area of the carpet and the length ofthe minimum possible side of the carpet, your task is to find how many types ofcarpets are possible. For example, the area of the carpet 12, and the minimumpossible side of the carpet is 2, then there can be two types of carpets andtheir 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 adenotes the area of the carpet and b denotes the minimum possible sideof the carpet.

Output

For each case, print the case number and the number ofpossible carpets.

Sample Input

Output for Sample Input

2

10 2

12 2

Case 1: 1

Case 2: 2


题意: 有一个矩形的毯子,已知它一定不是正方形,并且已知最短边和毯子的面积,求这个毯子可能有多少种形状。

分析:首先,如果最短的边大于等于面积的平方根,两个大于面积平方根的边不可能组成面积等于给定面积的矩形。

所以这种情况是0. 然后最短边的范围就变成了1-1e6,问题也变成了在最短边(min_side)到面积(area)这些数中有多少对不同的数相乘等于面积(area)。可以转变为1-area中不同的数相乘为area的对数,再减去1-min_side-1中不同的数相乘为area的对数。然后利用算术基本定理中的(1)算出1-area中的正因数的个数,正因数关于sqrt(area)对称,每对称的两个相乘是area,因此只要因数的个数除以二就行啦,向下取整,正好也不会算上平方根。再就是1-min_side-1中的对数,暴力就行啦。(下图是转的)



#include<bitset>
#include<map>
#include<vector>
#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<stack>
#include<queue>
#include<set>
#define inf 0x3f3f3f3f
#define mem(a,x) memset(a,x,sizeof(a))

using namespace std;

typedef long long ll;
typedef pair<int,int> pii;

inline ll in()
{
    ll res=0;char c;
    while((c=getchar())<'0' || c>'9');
    while(c>='0' && c<='9')res=res*10+c-'0',c=getchar();
    return res;
}
const int N=1000010;
int prime[79000];
bitset<N> vis;
int p;

void init()
{
    for(int i=2;i<N;i++)
    {
        if(!vis[i])
        {
            prime[p++]=i;
            for(int j=i+i;j<N;j+=i)
            {
                vis[j]=1;
            }
        }
    }
}
int main()
{
    int T=in();
    int ii=1;
    init();
    while(T--)
    {
        ll area=in(),min_side=in();
        if(min_side>=sqrt(area))
        {
            printf("Case %d: %d\n",ii++,0);
            continue;
        }
        ll tmp=area;
        int ans=1;
        for(int i=0;i<p && 1LL*prime[i]*prime[i]<=area;i++)
        {
            int cnt=0;
            while(area%prime[i] == 0)
            {
                area/=prime[i];
                cnt++;
            }
            ans*=(cnt+1);
        }
        if(area!=1) ans<<=1;
        ans>>=1;  //因数的个数除以二就是组数,同时排除了平方根
        for(int i=1;i<min_side;i++) if(tmp%i==0) ans--; //min_side此时是小于sqrt(area)的
        printf("Case %d: %d\n",ii++,ans);
    }
    return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值