题意:求区间[a,b]中b的因数对数有几个,[x,y]和[y,x]算一对。
因为x和y的范围是1e12,那么我们根据唯一分解定理,只需要求1到1e6范围内的质因数即可。
然后根据乘法原理:ans=ans*(质因数指数+1);最后ans除以2,就是b的所有因数对数。
然后用ans减去,小于a的对数就是我们要求的答案。
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <algorithm>
#include <math.h>
using namespace std;
typedef long long ll;
ll a[1100006];
ll prime[1000006];
ll num=0;
void init()
{
memset(a,0,sizeof(a));
for(ll i=2;i<=1100000;i++)
{
if(!a[i])
for(ll j=i*2;j<=1100000;j+=i) a[j]=1;
}
a[1]=1;
a[2]=0;
for(ll i=2;i<=1000006;i++)
if(!a[i]) prime[num++]=i;
}
ll solve(long long l,long long r,long long &ans)
{
ll op=r;
for(ll i=0;i<num;i++)
{
if(op<prime[i]) break;
if(op%prime[i]==0)
{
//printf("%d\n",prime[i]);
ll nu=0;
while(op%prime[i]==0)
{
op/=prime[i];
nu++;
}
ans*=nu+1;
}
}
if(op>1) ans*=2;
ans/=2;
}
int main()
{
init();
long long l,r;
ll t;cin>>t;ll cas=1;
while(t--)
{
cin>>r>>l;
ll q=sqrt(0.5+r);
if(l>q)
printf("Case %d: 0\n",cas++);
else
{
ll ans=1;
solve(l,r,ans);
for(ll i = 1; i < l; i++){
if(r % i == 0) ans -= 1;
}
printf("Case %d: %lld\n",cas++,ans);
}
}
return 0;
}