C - Aladdin and the Flying Carpet | 分解质因数 | 算术基本定理 | 数论 | 素数(疑问待解决)

题目大意是,给你两数x, y乘积和,与x,y所有取值情况中最小的可能的值,求x,y有多少种可能的情况。(也就是分解质因数)

算术基本定理:每个正整数都可以被唯一地写成素数的乘积(此时素数根据其大小按照升序排列)。

  • 关于getprime()函数 - 素数的线性筛法 预处理,先找出1e6以内的所有素数。因为题目范围里area是1e12,所以最大的质因数就是1e6。注意要写在for(, t, )的外面,不然每次都要调用。
  • 注意1e12的数据范围,函数内也要记得使用ll
  • getprime函数内部的循环for(int j = 1;j <= prime[0] && prime[j] <= MAXN / i;j++),prime[j] <= MAXN / i 是起什么作用?如果不加这一条,getprime就不会return
  • 还有ans *= (t+1); ans *= 2
#include <bits/stdc++.h>

using namespace std;

#define endl '\n'
#define ll long long
#define MAXN 1000010

int T;
ll area, minn;
int prime[MAXN];

void getprime()//线性筛找出1e6的所有素数
{
    memset(prime, 0, sizeof(prime));
    for(int i = 2;i <= MAXN;i++)
    {
        if(!prime[i])
        {
            prime[++prime[0]] = i;//用prime[0]代替了cnt的作用
        }
        for(int j = 1;j <= prime[0] && prime[j] <= MAXN / i;j++)
        {
            prime[prime[j]*i] = 1;

            if(i%prime[j] == 0)//关键步骤,降低复杂度,见上面链接
                break;
        }
    }
    //printf("return\n");
    return;
}

ll fun(ll area, ll minlen)//注意1e12的数据范围,必须用ll
{
    ll temp = area, ans = 1;

    if(minlen * minlen > area)//如果最小值都大于面积,那肯定没有成立的情况
        return 0;

    for(ll i = 1;prime[i] <= temp/prime[i];i++)
    {
        ll t = 0;
        if(temp % prime[i] == 0)
        {
            while(temp % prime[i] == 0)
            {
                t++;
                temp /= prime[i];
            }
            ans *= (t+1);
        }
    }
    if(temp != 1)
        ans *= 2;
    ans /= 2;

    for(ll m = 1;m < minlen;m++)
    {
        if(area % m == 0)
            ans--;
    }
    return ans;
}


int main()
{
    scanf("%d", &T);
    getprime();
    for(int t = 1;t <= T;t++)
    {
        scanf("%lld %lld", &area, &minn);

        printf("Case %d: %lld\n", t, fun(area, minn));

    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值