Aladdin and the Flying Carpet LightOJ - 1341 (唯一分解定理+线筛+一个数的因数个数)

传送门

题意:给两个数a,b,a为某个长方形的面积(不能为正方形),求长和宽都不小于b且面积为a的长方形的个数。

  • 1 ≤ b ≤ a ≤ 1e12
  • 多组输入T<=4000

题解:唯一分解定理求a的因数个数,然后除2取整(懂的都懂,另外如果存在sqrt(a)*sqrt(a)=a,也是这样,不用特意考虑,所以count部分完全模板)。然后cnt暴力计数小于b的数是否a%i==0(这里注意可能3*4=a=12,b=5,会记录两次,但是不用考虑,可以直接特判b*b>=a 返回答案0,懂的都懂)。

答案为count(x)/2-cnt。

复杂度最高O(4e9)勉强过了(感觉数论都是这种最高1e9+,但是一般都不会达到。忽悠人?建议循环变量外置)。

ps:听别人说唯一分解定理之后可以快速求出这个数的所有因数???反正网上没人写这个代码的样子。

代码:

#include <bits/stdc++.h>
#define int long long
#define read(x) scanf("%lld", &x)
#define print(a, c) printf("%lld%c", a, c)
#define dbg(x) cout << #x << "===" << x << endl
using namespace std;
const int N = 1e6 + 10;

int a, b;

int prime[N], vis[N];
void init(int n) {
    for (int i = 2; i <= n; i++) {
        if (vis[i]) continue;  //非素数
        prime[++prime[0]] = i;
        for (int j = i + i; j <= n; j += i) vis[j] = 1;
    }
}
//先素数筛算是一个优化,大概能优化一个数量级吧
int count(int x) {
    int res = 1, i, a;
    //从1开始,prime[0]为素数个数
    //不能等于,因为不能为正方形
    //不过,尽管大胆一点去分解,若存在sqrt(x)*sqrt(x)=x,无非因数个数为奇数
    for (i = 1; prime[i] * prime[i] <= x && i <= prime[0]; i++) {
        a = 0;
        while (x % prime[i] == 0) a++, x /= prime[i];
        res *= (a + 1);  //很多*1
    }
    if (x > 1) res *= (1 + 1);
    return res;
}
signed main() {
    init(N - 1);
    int T;
    read(T);

    int ans, cnt, i;
    for (int _ = 1; _ <= T; _++) {
        read(a), read(b);
        ans = 0;
        if (b * b >= a)
            ans = 0;
        else {
            cnt = 0, i;
            for (i = 1; i < b; i++)
                if (a % i == 0) cnt++;
            ans = count(a) / 2 - cnt;
        }
        printf("Case %lld: %lld\n", _, ans);
    }
    return 0;
}

补充:蜜汁复杂度,如果严格按照要求的最大限制,那么上面的做法和下面暴力差不多吧。这题应该只是卡了下面这种做法。事实上应该可以互补,比如b太大就下面这种,太小就上面这种。感觉也优化不到什么emm

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值