题意:给出两个数a和b,a,b <= 10^12,a代表矩形的面积,b代表矩形最短边的下限。问有多少种满足条件的矩形。
题解:唯一分解定理
1.唯一分解定理:
N = p1^a1*p2^a2*p3^a3* ... *pn^an(其中p1、p2、... pn为N的因子,a1、a2、... 、an分别为因子的指数)
N的因子个数 M = (1 + a1)*(1 + a2)*(1 + a3)*...*(1 + an);
2.通过唯一分解定理,算出a的因子数,因题目是对数,故除以2,再减去小于最短边下限的情况,即可求出答案。
#include<math.h>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#define N 1000005
using namespace std ;
int num = 0 ;
long long prime[N] ;
bool vis[N] ;
void Euler()
{
long long i , j ;
memset(vis , 0 , sizeof(vis)) ;
for(i = 2 ; i <= N - 5 ; i ++)
{
if(vis[i])
continue ;
prime[num ++] = i ;
for(j = 1 ; j * i <= N - 5 ; j ++)
vis[j * i] = 1 ;
}
}
long long solve(long long x) //唯一分解定理求因子数
{
int i , j ;
int a ;
long long sum = 1 ;
for(i = 0 ; i < num && prime[i] * prime[i] <= x ; i ++)
{
a = 0 ;
while(x % prime[i] == 0)
{
x /= prime[i] ;
a ++ ;
}
sum *= (1 + a) ;
}
if(x > 1)
sum *= 2 ; //最后可能剩余一个质数(大于sqrt(x))分解不了,需要乘2
return sum ;
}
int main()
{
int i , j , k ;
int t , cnt = 0 ;
long long ans ;
long long a , b ;
Euler() ; //筛素数
scanf("%d" , &t) ;
while(t --)
{
scanf("%lld%lld" , &a , &b) ;
if(a < b * b) //这一步卡了b的范围(b<=10^6)使最后减去最短边小于b的判定时间缩短
{
printf("Case %d: 0\n" , ++cnt) ;
continue ;
}
ans = solve(a) ; //计算出a的总因子数
ans /= 2 ; //本题要求的是因子对数,故除2
for(i = 1 ; i < b ; i ++)//减去最短边小于b的情况
if(a % i == 0)
ans -- ;
printf("Case %d: %lld\n" , ++cnt , ans) ;
}
}