题目
描述
原题目太啰嗦,我简化一下
在
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!)̸=1且n!̸≡0(modi)
输入
一个数
N
≤
1
e
6
N\leq1e6
N≤1e6
输出
表示满足要求的位置数量,答案对取模
1
e
9
+
7
1e9+7
1e9+7输出
样例输入
4
样例输出
9
思路
n
!
−
n
!
的
约
数
个
数
数
−
与
n
!
以
内
互
质
的
数
+
1
(
1
被
多
减
了
一
次
)
n!-n!的约数个数数 -与n!以内互质的数+1(1被多减了一次)
n!−n!的约数个数数−与n!以内互质的数+1(1被多减了一次)
不知道怎么求得看这里
因为有除法,
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;
}