题面
我们定义不存在
d
d
使得的数
x
x
为好数。
那么对于一个排列的
t(p)
t
(
p
)
显然是最后一个好数的出现位置。
线性筛求出好数个数
m
m
。
枚举最后一个好数的出现位置,那么满足的排列的个数有
(i−1m−1)m!(n−m)!
(
i
−
1
m
−
1
)
m
!
(
n
−
m
)
!
个,其中
n=r−l+1
n
=
r
−
l
+
1
。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#define N 10000010
#define ll long long
using namespace std;
const int mod=1000000007;
int L,R,pri[N],num,minp[N],cnt;
ll fac[N],ifac[N],ans;
ll ksm(ll a,int b){ll r=1;for(;b;b>>=1){if(b&1)r=r*a%mod;a=a*a%mod;}return r;}
void getpri(int n)
{
for(int i=2;i<=n;i++)
{
if(!minp[i]) {pri[++num]=i;minp[i]=i;}
for(int j=1;j<=num&&i*pri[j]<=n;j++)
{
minp[i*pri[j]]=pri[j];
if(i%pri[j]==0) break;
}
}
}
int main()
{
scanf("%d%d",&L,&R);
fac[0]=1;
for(int i=1;i<=R;i++)
fac[i]=fac[i-1]*i%mod;
ifac[R]=ksm(fac[R],mod-2);
for(int i=R-1;i>=0;i--)
ifac[i]=ifac[i+1]*(i+1)%mod;
getpri(R);
cnt=0;
for(int i=L;i<=R;i++)
if(minp[i]==0||i/minp[i]<L) cnt++;
int len=R-L+1;ans=0;
for(int i=cnt;i<=len;i++)
ans=(ans+fac[len-cnt]*ifac[i-cnt]%mod*cnt%mod*fac[i-1]%mod*i)%mod;
printf("%lld",ans);
return 0;
}