题意就是:给你两个数,然后让你去求第一个数分解的因子对数,其中要求因子对中的任意两个数都必须大于第二个数,声明对于(2,6)和(6,2)是一个因子对。
分析:先利用唯一性分解的方法对第一个数进行分解,然后根据定理这个数的因子个数为(1+a1)(1+a2)。。。(1+an)然后再除以2得到因子对个数,再根据第二个数来减去相应的值。对于这道题主要是学习到了唯一性定理中关于因子个数的计算,这一点是我所不知道的,也是我感觉是这道题求解的重点,其次就是一些细节的处理,比如关于第二个数和第一个数关系的特判,以及我在素数筛选时,int的爆范围等等,都是以后应该注意到的地方。
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cstdlib>
#include<cmath>
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 10;
bool isprime[maxn];
ll prime[maxn], k;
void ini()
{
memset(isprime, true, sizeof isprime);
memset(prime, 0, sizeof prime);
}
void check()
{
//isprime
k = 0;
int re = sqrt(maxn);
for (int i = 2; i <maxn; i++)
{
if (isprime[i])
{
prime[k++] = i;
for (long long j =(long long) i * i; j < maxn; j += i) isprime[j] = false;
}
}
}
ll solve(ll num)
{
ll sum = 1;
for (int i = 0; i < k&&prime[i] * prime[i] <= num; i++)
{
if (num%prime[i] == 0)
{
ll ans = 0;
while (num%prime[i] == 0)
{
ans++;
num /= prime[i];
}
sum *= (1 + ans);
}
}
if (num > 1) sum *= 2;
return sum;
}
int main()
{
int t;
scanf("%d", &t);
ini();
check();
for (int i = 1; i <= t; i++)
{
ll area, a;
scanf("%lld %lld", &area, &a);
if (area < a*a)
{
printf("Case %d: 0\n", i);
continue;
}
ll res = solve(area);
res /= 2;
for (int j = 1; j < a; j++) if (area%j == 0) res--;
printf("Case %d: %lld\n", i, res);
}
//system("pause");
return 0;
}