[HZOI] 弹药科技

题目描述

经过精灵族全力抵挡,精灵终于坚持到了联络系统的重建,于是精灵向人类求助,
大魔法师伊扎洛决定弓}用博士的最新科技来抗敌。
伊扎洛:“博士,还没好吗?”
博士:“只差一步了!只需要在正确的位置装上弹药就可以了!”
博士的最新科技是全新的炸弹,但是现在还需要一步装弹药的操作。博士的炸弹有
N!个位置可以装弹药(>.<),但是只有在正确的位置装上弹药才能启动,博士将
装弹药的位置编号为1到N!,一个位置i需要装弹药,当且仅当gcd(i, N!) ≠ 1且
N! mod i ≠ 0,现在博士不要求你求出所有装弹药位置,只需要你求出满足要求
的位置的数量就可以了。

数据范围

N <= 1000000

————————————分界线——————————————

题解

首先当我们看到这个数据范围的时候
N <= 1000000
再看到要求算n!
心里肯定是无数只草泥马跑过了吧
—————————————进入正题——————————————
放导弹的位置满足
gcd(i, N!) ≠ 1且 N! mod i ≠ 0
从这里面我们便可以推出
=>i 为 与 n! 不互质的数 and i不是n! 的因子
而我们要求的这个答案即n! - ans1 - ans2 + 1
(ans1 代表与n! 互质的数的个数,ans2为因子数,同时1被重复计算了,所以需要-1)

我们进行分部解决,将ans1与ans2分步解决

因子数

根据唯一分解定律, 任意数t = p1 ^ a1 + p2 ^ a2 + … + pn ^ an
t的因数个数为ans = Π (ai + 1)
根据Legendre定理
在这里插入图片描述
证明
在这里插入图片描述
使用这个定理,我们就可以找出a[i]了,当然,应该先Euler筛法走一波

    for (int i = 1;i <= cnt; i++)
    {
   
   
        k = 1;
        ///一定记得将k清1啊
        ///在正数n!的素因子标准分解式中, 素数p的最高指数记作pn[n!]
        ///则pn[n!] = Σ(k >= 1) ceil(n / p ^ k)
        for (int j = 1;k * prime[i] <= n; j++)
            k *= prime[i] ,pn[i] += n / k;
        ///第j时即为prime[i] ^ j
    }

然后我们就可以使用我们的唯一分解定理将n!的因子数筛出来
只需要枚举每一个质数即可

for (int i = 1;i <= cnt; i++)
    ans2 = ans2 * (pn[i] + 1) % mod;
    ///性质
    ///根据唯一分解定律, 任意数t = p1^a1 + p2^a2 + ... + pi^ai
    ///t的因数个数为ans = Π (ai + 1)

与 n! 互质的数

回想一下,与n互质的数,不就是Euler函数φ(n)吗
那么n!的φ应该如何求呢
这个时候
我们需要调用Euler函数的另一种求法(单纯求一个)

int phi (int n)
{
   
   
    int res = n;
    for (int i = 2</
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值