题目链接:https://vjudge.net/contest/318269#problem/B
Sample Input
2
10 2
12 2
Sample Output
Case 1: 1
Case 2: 2
翻译:
给你矩形(不能是正方形)的面积(矩形的边长都是正整数),让你求最小的边大于等于b的矩形的个数。
转化为数学表达式:求c*d=a且c>=b且d>=b的二元组对数。
知识点:
唯一分解定理:
任何一个大于1的自然数 N,如果N不为质数,那么N可以唯一分解成有限个质数的乘积。
p1,p2…pn都为素数,a1,a2…an对应的是素数的几次幂。
可以推出:N的因子总个数即为图中的公式表示。
分析:
1.
a b (1 ≤ b ≤ a ≤ 10^12)。b为最小的边长,下一个边长必须大于或等于b。所以,素数打表处理时,只需要最大处理到10 ^6即可。
2.
先计算a有多少个因子数。根据唯一分解定理,找到a的素因子,看看a能分成几个这样的素因子。累乘,算出a的总因子数。
3.
对总因子数/2,算出有多少对二元组。对于小于b的数,对数减减。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define LL long long
#define N 1000100
int k,book[N],pr[N];
void prime()
{
k=0;
memset(book,0,sizeof(book));
book[1]=1;
for(int i=2; i<N; i++)
{
if(book[i]==0)
{
pr[k++]=i;/*将素数存到pri数组中*/
for(int j=2*i; j<N; j+=i)
book[j]=1;
}
}
}
LL solve(LL a)
{
LL sum=1;
for(LL i=0; i<k&&pr[i]*pr[i]<=a; i++)
{
if(a%pr[i]==0)/*这个a能被分解为素数pr[i]*/
{
int ans=0;
while(a%pr[i]==0)
{
ans++;/*这个素数能被分解多少个*/
a=a/pr[i];
}
sum*=(1+ans);
}
}
if(a>1)/*剩一个单独的素因子*/
sum*=2;
return sum;
}
int main()
{
int T;
scanf("%d",&T);
prime();
int f=1;
while(T--)
{
LL a,b;
scanf("%lld %lld",&a,&b);
if(b*b>=a)
{
printf("Case %d: 0\n",f++);
continue;
}
LL num=solve(a);
num/=2;/*有多少对二元组*/
for(int i=1; i<b; i++)
{
if(a%i==0)
num--;
}
printf("Case %d: %lld\n",f++,num);
}
return 0;
}