题意
有一块矩形(也可能是正方形)的飞毯。
给定飞毯的面积(n)和最小可能的边长(a),求可能有多少种不同边长的飞毯。((1<=a<=n<=1e12))
如面积(n=6)时,({2,3})和({3,2})算一种。
题解
本来想(sqrt(n))的复杂度直接枚举(n)的所有因数,发现(TLE)了。
正解是把(n)质因数分解成(n=a_1^{b_1}a_2^{b_2}...a_n^{b_n}),然后(n)的因子的个数就是((1+b_1)*(1+b_2)...(1+b_n))。
我自做聪明的把上面得出的结果加上(1)(考虑到因子有(1)的情况),结果WA了一晚上。
得出(n)的因子个数之后,再暴力枚举小于(b)的数,如果是(n)的因数就减掉。
代码
#include <bits/stdc++.h>
#define FOPI freopen("in.txt", "r", stdin)
#define FOPO freopen("out.txt", "w", stdout)
#define FOR(i,x,y) for (int i = x; i <= y; i++)
#define ROF(i,x,y) for (int i = x; i >= y; i--)
using namespace std;
typedef long long LL;
const int N = 1e6 + 10;
int Prime[N+100];
void getPrime(int N)
{
memset(Prime, 0, sizeof(Prime));
FOR(i, 2, N)
{
if (!Prime[i]) Prime[++Prime[0]] = i;
for (int j = 1; j <= Prime[0] && Prime[j] <= N/i; j++)
{
Prime[Prime[j]*i] = 1;
if (i % Prime[j] == 0) break;
}
}
}
int factor[N+100][2];
int facCnt;
LL Factor(LL x)
{
facCnt = 0;
LL tmp = x;
for (int i = 1; Prime[i] <= tmp/Prime[i]; i++)
{
factor[facCnt][1] = 0;
if (tmp % Prime[i] == 0)
{
factor[facCnt][0] = Prime[i];
while(tmp % Prime[i] == 0)
{
factor[facCnt][1]++;
tmp /= Prime[i];
}
facCnt++;
}
}
if (tmp != 1)
{
factor[facCnt][0] = tmp;
factor[facCnt++][1] = 1;
}
LL res = 1;
FOR(i, 0, facCnt-1)
res *= (1+factor[i][1]);
return res;
}
LL n, b;
int t;
int main()
{
getPrime(N);
scanf("%d", &t);
FOR(ca, 1, t)
{
scanf("%lld %lld", &n, &b);
if (n < b*b)
{
printf("Case %d: 0
", ca);
continue;
}
LL Sum1 = Factor(n) / 2;
FOR(i, 1, b-1)
if (n % i == 0) Sum1--;
printf("Case %d: %lld
", ca, Sum1);
}
}