思路就是把a分解质因数,对于一个质因数a1p1,会是a的因数多(p1+1)倍(不选或者选几个,乘法法则),对于每个因数,都会有另一个因数与他乘在一起结果是a,所以我们求出因数的个数之后除以2即可得出组合的数量,然后对于给的范围,0~b中每有一个因数,组合的数量便会减一。
如果我们需要对N分解质因数,只要把质数表打到N1/2即可,因为不可能有两个质因数都大于N1/2。
#include <iostream>
#include <algorithm>
#include <string>
#include <stdio.h>
#include <cstdlib>
#include <math.h>
#include <cstring>
#include <iomanip>
#include <vector>
using namespace std;
#define ll long long
const ll N = 1e6+7;
#define INF 0x3f3f3f3f
ll n,m;
ll prime[N];
bool vis[N];
void shai(ll n){
ll i,j;
ll m = (ll)sqrt(n);
for(i = 2; i <= m;i++){
if(!vis[i]){
for(j = i*i;j<=n;j+=i){
vis[j] = 1;
}
}
}
}
ll top;
void insert(){
ll i;
top = -1;
for(i=2;i<N;i++){
if(!vis[i]){
top++;
prime[top] = i;
}
}
}
int t,cases;
int main(){
shai(N-1);
insert();
ll i,j;
scanf("%d",&t);
while (cases < t)
{
cases++;
scanf("%lld%lld",&n,&m);
if(m > sqrt(n)){
printf("Case %d: 0\n",cases);
continue;
}
ll tmp = n;
ll ans = 1;
for(i=0; i <= top && prime[i]*prime[i] <= tmp;i++){
if(tmp % prime[i] == 0){
ll cnt = 0;
while (tmp % prime[i] == 0)
{
cnt++;
tmp/=prime[i];
}
ans *= (cnt + 1);
}
}
if(tmp > 1){
ans *= 2;//最后剩下的一定是个质数,如果剩下的是两个质数的乘积,小的一定会在前面被处理掉
}
ans /= 2;//顺便消去25的5这样的因数
for(i=1;i<m;i++){
if(n%i == 0){
ans--;
}
}
printf("Case %d: %lld\n",cases,ans);
}
return 0;
}