LightOJ 1341 - Aladdin and the Flying Carpet

Sample Input
2
10 2
12 2

Sample Output
Case 1: 1
Case 2: 2

题目大意:给你两个数a和b,a是长方形的面积(这个长方形是非常单纯的长方形,他没有两条相等的边),长方形的宽大于等于b(,不管宽怎么膨胀,宽是永远小于长滴)。而我们就是要求出满足条件的长宽的对数。

解题思路:因为今天刚学的唯一分解定理,知道要用,但不知道如何用,所以就看了看dalao的题解,恍然大悟~~,唯一分解定理有以下几条应用:
在这里插入图片描述
目前我也只懂前两条,太菜了,显然,这题需要用到定理的第一条,那应该怎么用呢,首先我们可以利用第一条求出a的正因子个数除以2就是长宽的对数,然后求出[1,b)内a的正因子个数,两者一减,就是所求的结果了。

Code:

#include<iostream>
#include<cmath>
#include<cstring>
#include<vector>
#include<map>

using namespace std;
typedef long long ll;
const int maxn = 1e6+10;
bool p[maxn];
ll prime[maxn],cnt;

void get_prime(){//素数打表 
	cnt=0;
	memset(prime,0,sizeof(prime));
	memset(p,0,sizeof(p));
	for(ll i=2;i<maxn;i++){
		if(!p[i]){
			prime[cnt++]=i;
			for(ll j=i+i;j<maxn;j+=i){
				p[j]=1;
			}
		}
	}
}

ll cont(ll a){//求a的正因子个数 
	ll ans=1;
	ll i=0,num=0;
	while(prime[i]<a&&i<cnt){
		while(a%prime[i]==0){
			a/=prime[i];
			num++;
		}
		ans*=(num+1);
		num=0;
		i++;
	}
	if(a>1) ans*=1+1;
	return ans;
}

int main(){
	int t,k=1;
	get_prime();
	scanf("%d",&t); 
	while(t--){
		ll a,b;
		ll cnt=0;
		scanf("%lld %lld",&a,&b);
		if(b>=sqrt(a)){//如果b大于等于a的平方根,那么长宽的乘积就会大于等于a,而长宽不能相等。 
			printf("Case %d: %lld\n",k++,0);
			continue;
		}
		for(ll i=1;i<b;i++){
			if(a%i==0) cnt++;
		}
		ll temp=cont(a)/2;
//		cout<<temp<<" "<<cnt<<endl;
		printf("Case %d: %lld\n",k++,temp-cnt);
	}
	
	return 0;
}
posted @ 2019-08-12 17:15  voids5  阅读(93)  评论(0编辑  收藏  举报