题目描述
经过精灵族全力抵挡,精灵终于坚持到了联络系统的重建,于是精灵向人类求助,
大魔法师伊扎洛决定弓}用博士的最新科技来抗敌。
伊扎洛:“博士,还没好吗?”
博士:“只差一步了!只需要在正确的位置装上弹药就可以了!”
博士的最新科技是全新的炸弹,但是现在还需要一步装弹药的操作。博士的炸弹有
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</