lightoj1341——唯一分解定理+线筛

题目链接: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;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值