您的位置:首页 > 其它

Lightoj1341——Aladdin and the Flying Carpet(算术基本定理)

2016-08-05 11:17 423 查看
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: a b (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

题目给出a和b,a表示长方形的面积,b表示可能的最小的边,要求满足最小边不小于b的长方形的个数,且题目中提到不能为正方形。

算术基本定理:任何一个大于1的自然数 N,如果N不为质数,那么N可以唯一分解成有限个质数的乘积 N=P1a1P2a2P3a3……Pnan。——百度百科

那么就有以下推论



本题就是第一条推论的应用,求出a的正因子的个数,因为题目是要求满足最小边的个数,因此解最多是正因子个数的一半,再减去小于b即不满足题意的正因子的个数。另外还要特判b*b>=a的情况,不然会超时。

#include <iostream>
#include <cstring>
#include <string>
#include <vector>
#include <queue>
#include <cstdio>
#include <map>
#include <cmath>
#include <algorithm>
#define INF 0x3f3f3f3f
#define MAXN 1000005
#define mod 1000000007
using namespace std;
long long p[MAXN],a[MAXN],cnt=0;  //p保存素数,a判断当前数是否为素数
void Primer()
{
int i,j, k;
for(i=2;i<MAXN;++i)   //i从2开始遍历
{
if(a[i]==0)    //a[i]==0说明该i是素数
p[cnt++]=i;   //cnt作为地址标志
for(j=0;j<i&&(k=i*p[j])<MAXN;++j)   //j从0开始遍历,k作为有质数p[j]的合数
{
a[k]=1;    //合数设1
if(i%p[j]==0)
break;
}
}
}
long long fac(long long x)
{
long long ans=1,tmp=0;
for(int i=0;i<cnt&&p[i]*p[i]<=x;++i)
{
tmp=0;
if(x==1)
break;
while(x%p[i]==0)
{
tmp++;
x/=p[i];
}
ans*=(tmp+1);
}
if(x!=1)
ans*=2; //如果x还没被整除,说明还剩下一个素数,此时tmp=1
return ans;
}
int main()
{
Primer();
int t,cnt=1;
long long a,b,ans;
scanf("%d",&t);
while(t--)
{
scanf("%lld%lld",&a,&b);
if(b*b>=a)
{
printf("Case %d: 0\n",cnt++);
continue;
}
ans=fac(a);
ans/=2;
for(long long i=1;i<b;++i)
{
if(a%i==0)
ans--;
}
printf("Case %d: %lld\n",cnt++,ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: