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\) 的质数,有时候就需要像代码中第一个注释那儿特判一下

浙公网安备 33010602011771号