Aladdin and the Flying Carpet

题目大意:

给一组数字 \(a\)\(b\) 。其中,\(a\) 表示一个长方形的面积,现在想知道有多少种整数的边的组合可以组成面积为 \(a\) 的矩形,而且要求矩形的最短的边不得小于 \(b\)
注意:不能是正方形
第一行是一个整数 \(T\) (\(T\)≤ 4000) 表示数据的组数 每组数据包含两个整数: \(a\),\(b\) (1 ≤ \(b\)\(a\) ≤ 1012) 其中 \(a\) 表示矩形的面积 ,\(b\) 为最小边.

前置知识:唯一分解定理
\(a\) 进行质因数分解,得到 $$a = p_1^{x_1} + p_2^{x_2} + ... +p_n^{x_n}$$
那么易得,a的因子个数为 $$cnt(a) = \prod_{i=1}^n{ {x_i + 1}} $$
补充一下,a的各因子的和为$$ sum(a) = \prod_{i=1}^n{ {p_i^{a_i + 1}} \over {p_i - 1}} $$

本题的思路就很明晰了:先将面积进行质因数分解,求出因子的个数,除以二得到因子对数,再进行边长度小于 \(b\) 的情况即可

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int MAXN = 900000;
bool vis[MAXN + 5];
vector<int> prime;
int t;
void get_prime(){
	for(int i = 2; i <= MAXN; i++){
		if(!vis[i])prime.push_back(i);
		for(int j = 0; j < prime.size() && i * prime[j] <= MAXN; j++){
			vis[i * prime[j]] = 1;
			if(i % prime[j] == 0)break;
		}
	}
}
int get(int n){
	int sum = 1;
	for(int i = 0; i < prime.size() && prime[i]<= n; i++){
		if(n % prime[i] == 0){
			int ans = 0;
			while(n % prime[i] == 0){
				n /= prime[i];
				ans++;
			}
			sum *= (ans + 1);
		}
		
	}
	if(n > 1)sum *= 2;//如果n不为一,说明它此时一定是一个质数,然而这个质数因为太大没能筛到,所以应该特殊处理一下
	return sum;
}
int a,b;
signed main(){
	//freopen("b.out","w",stdout); 
	cin >> t;
	get_prime();
	int cnt = 0;
	while(t--){
		cin >> a >> b;
		int num = 0;
		if(a <= b * b){//处理特殊情况 
			printf("Case %d: 0\n",++cnt);
			continue;
		}
		num = get(a);
		num /= 2;
		for(int i = 1; i < b; i++){//如果边的长度小于b,那么对数减一 
			if(a % i == 0)num--;
		}
		printf("Case %d: %d\n",++cnt,num);
	}
	
}

很多时候,在做质因数分解的题时,筛质数时一班只筛到 \(\sqrt{n}\) 左右就行了,但是也不排除 \(n\) 是一个大于 \(n\) 的质数,有时候就需要像代码中第一个注释那儿特判一下

posted @ 2022-07-13 16:23  腾云今天首飞了吗  阅读(45)  评论(0)    收藏  举报