题目链接:http://lightoj.com/volume_showproblem.php?problem=1341
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是一个长方形的面积,问有多少种整数的边的组合可以组成面积为a的长方形,要求最短的边不得小于b。
题意很好理解,但是根据给的数据的范围,我们暴力的话,过不了,而且我们可以知道b最大范围为10^6,因此我们可以换个思路去做,根据唯一分解定理,我们可以求出a的所有正因数个数,再除以2就是对数,但是我们求的过程中1到b的a的约数多算了,因此我们可以暴力的去求1到b范围内a的约数,最后相减可以的答案。
在求a的因子个数时,我们不能直接求,会超时,需要用线筛(或者埃筛)预处理一下,之后再求就行了。
#include<iostream>
#define ll long long
using namespace std;
const int maxn=1e6+10;
bool visited[maxn];//visited[i]表示i是不是质数
int prime[maxn], tot;//prime[N]用来存质数
void init(){//线筛
for(int i = 2; i < maxn; i ++) visited[i] = true;//初始化为质数
for(int i = 2; i < maxn; i++){
if(visited[i]) prime[tot ++] = i;//把质数存起来
for(int j = 0; j < tot && i * prime[j] < maxn; j++){
visited[i * prime[j]] = false;
if(i % prime[j] == 0) break;//保证每个合数被它最小的质因数筛去
}
}
}
ll count(ll n){//唯一分解定理求正因子个数
ll s=1;
ll a;
for(ll i=0;prime[i]<n&&i<tot;i++){
a=0;
if(n%prime[i]==0){
while(n%prime[i]==0){
n/=prime[i];
a++;
}
}
s*=(a+1);
}
if(n>1) s*=2;
return s;
}
int main(){
int T;
scanf("%d",&T);
ll a,b;
init();
for(int kcase=1;kcase<=T;kcase++){
scanf("%lld%lld",&a,&b);
ll ans=0;
if(b*b>a)//a,b不符合条件
ans=0;
else{
ll cnt=0;
for(ll i=1;i<b;++i)//求1到b区间有多少个a的约数,注意不包含b
if(a%i==0)
cnt++;
ans=count(a)/2-cnt;
}
printf("Case %d: %lld\n",kcase,ans);
}
return 0;
}