题目大意是,给你两数x, y乘积和,与x,y所有取值情况中最小的可能的值,求x,y有多少种可能的情况。(也就是分解质因数)
算术基本定理:每个正整数都可以被唯一地写成素数的乘积(此时素数根据其大小按照升序排列)。
- 关于getprime()函数 - 素数的线性筛法 预处理,先找出1e6以内的所有素数。因为题目范围里area是1e12,所以最大的质因数就是1e6。注意要写在for(, t, )的外面,不然每次都要调用。
- 注意1e12的数据范围,函数内也要记得使用ll
- getprime函数内部的循环for(int j = 1;j <= prime[0] && prime[j] <= MAXN / i;j++),prime[j] <= MAXN / i 是起什么作用?如果不加这一条,getprime就不会return
- 还有ans *= (t+1); ans *= 2
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define ll long long
#define MAXN 1000010
int T;
ll area, minn;
int prime[MAXN];
void getprime()//线性筛找出1e6的所有素数
{
memset(prime, 0, sizeof(prime));
for(int i = 2;i <= MAXN;i++)
{
if(!prime[i])
{
prime[++prime[0]] = i;//用prime[0]代替了cnt的作用
}
for(int j = 1;j <= prime[0] && prime[j] <= MAXN / i;j++)
{
prime[prime[j]*i] = 1;
if(i%prime[j] == 0)//关键步骤,降低复杂度,见上面链接
break;
}
}
//printf("return\n");
return;
}
ll fun(ll area, ll minlen)//注意1e12的数据范围,必须用ll
{
ll temp = area, ans = 1;
if(minlen * minlen > area)//如果最小值都大于面积,那肯定没有成立的情况
return 0;
for(ll i = 1;prime[i] <= temp/prime[i];i++)
{
ll t = 0;
if(temp % prime[i] == 0)
{
while(temp % prime[i] == 0)
{
t++;
temp /= prime[i];
}
ans *= (t+1);
}
}
if(temp != 1)
ans *= 2;
ans /= 2;
for(ll m = 1;m < minlen;m++)
{
if(area % m == 0)
ans--;
}
return ans;
}
int main()
{
scanf("%d", &T);
getprime();
for(int t = 1;t <= T;t++)
{
scanf("%lld %lld", &area, &minn);
printf("Case %d: %lld\n", t, fun(area, minn));
}
return 0;
}