您的位置:首页 > 其它

Aladdin and the Flying Carpet LightOJ - 1341 (唯一分解定理求因数个数)

2019-01-15 17:01 405 查看

Aladdin and the Flying Carpet LightOJ - 1341

 

题面:

给一对数字 a,b ,a是一个长方形的面积,问有多少种整数的边的组合可以组成面积为a的长方形,要求最短的边不得小于b

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

思路:

首先我们需要知道如何快速计算一个数的因数个数。

       1.运用唯一分解定理可以将一个数x转化成 x = a1^p1 + a2^p2 + a3^p3 +...+ an^pn 这样的形式

       2.根据欧拉老爷爷给出来的公式,这个数x的因子个数n等于 (p1+1) × (p2+1) × (p3+1) ×...× (pn+1)

于是现在我们知道了数a有多少个因数n,那么因子个数n除以二就是可以组成的长方形的数量ans

最后枚举一下小于b的因子个数y

然后最后的结果就是ans-y

代码:

[code]#include <bits/stdc++.h>
using namespace std;
map<long long,int>ma;
int main()
{
//freopen("in.txt","r",stdin);
int t;
scanf("%d",&t);
for(int j=1; j<=t; j++)
{
long long a,b;
scanf("%lld%lld",&a,&b);
if(b*b>a)
{
printf("Case %d: 0\n",j);
continue;
}
int ans=ma[a];
long long x = a;
if(ans==0)
{
ans++;
for(int i=2; (long long)i*i<=a; i++)
{
int cnt=0;
if(a%i==0)
{
while(1)
{
if(a%i!=0)
break;
cnt++;
a/=i;
}
ans *= (cnt+1);
//cout<<" "<<cnt<<"\n";
}
}
if(a>1) ans*=2;
ans /= 2;
ma[x]=ans;
}
for(int i=1; i<b; i++)
{
if(x%i==0)
ans--;
}
printf("Case %d: %d\n",j,ans);
}
return 0;
}

PS: 因为暴力使用唯一分解定理会超时,所以有两个办法解决,一个是素数打个表可以快一些,第二个就是记忆化(偷懒用的,比赛不敢用)

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: