弹药科技(数论逆元,legendre)

文章目录


题目

描述
原题目太啰嗦,我简化一下
1 1 1 n ! n! n以内有多少个数不与 n ! n! n互质且不为 n ! n! n的因子
g c d ( i , n ! ) ≠ 1 且 n ! ̸ ≡ 0 ( m o d i ) gcd(i,n!)\neq 1且 n!\not\equiv0\pmod i gcd(i,n!)̸=1n!̸0(modi)
输入
一个数 N ≤ 1 e 6 N\leq1e6 N1e6
输出
表示满足要求的位置数量,答案对取模 1 e 9 + 7 1e9+7 1e9+7输出
样例输入
4
样例输出
9

思路

n ! − n ! 的 约 数 个 数 数 − 与 n ! 以 内 互 质 的 数 + 1 ( 1 被 多 减 了 一 次 ) n!-n!的约数个数数 -与n!以内互质的数+1(1被多减了一次) n!n!n+11
不知道怎么求得看这里
因为有除法, n ! n! n!又很大,所以预处理逆元

#include <cstdio>
#include <iostream>
using namespace std;
#define mod 1000000007
#define M 1000005
#define LL long long
 
LL n, tot, cnt, tot1;
int p[M], w[M], v[M];
 
LL rf[M];
 
inline void prepare(){
    tot = tot1 = 1;
    rf[0] = rf[1] = 1;
    for(int i = 2; i <= n; i ++){
        tot = (1ll*tot*i)%mod;
        rf[i] = 1ll*rf[mod%i]*(mod-mod/i)%mod;
        tot1 = (1ll*tot1*i)%mod;
        if( v[i] == 2 )
            tot1 = tot1*(i-1)%mod*rf[i]%mod;
    }
    tot -= tot1;
    if( tot < 0 )
        tot = (tot+mod)%mod;
}
 
inline void sieve(int x){
    for(int i = 2; i <= x; i ++){
        if( !v[i] ){
            v[i] = 2;
            p[++cnt] = i;
        }
        for(int j = 1; j <= cnt && i*p[j] <= x; j ++){
            v[p[j]*i] = 1;
            if( i%p[j] == 0 )
                break;
        }
    }
}
 
int main(){
    scanf("%lld",&n);
    sieve(n);
    prepare();
    for(int i = 1; i <= cnt; i ++){
        LL tmp = p[i];
        while( tmp <= n ){
            w[i] += n/tmp;
            tmp *= p[i];
        }
    }
    tot1 = 1;
    for(int i = 1; i <= cnt; i ++)
        tot1 = (tot1*(w[i]+1))%mod;
    printf("%lld\n", (tot-tot1+mod+1)%mod);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值