人生第二道可怜题,依旧来自于(JXOI)
首先发现这个东西长得和分手是祝愿差不多,于是考虑一下贪心
显然贪心的策略应该是从小到大一个一个试,遇到一个不能表示成前面的数的倍数的数就把这个数选上
先用类似埃筛的东西求出这样的数的个数(m)
如果(t(p)=i),那么这(m)个都必须在(i)步之前完成,而且第(i)个正好要是这(m)中的一个
于是答案就是
[sum_{i=m}^ni imes m imes A(i-1,m-1) imes (n-m)!
]
就是强行枚举在第(i)步完成,之后让第(i)次访问一个没有被筛到的,剩下的(m-1)个我们让排列在前(i-1)个位置里,剩下(n-m)个没啥用的我们让它们排列一下
就没了
代码
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<bitset>
#define maxn 10000005
#define re register
#define LL long long
const LL mod=1e9+7;
std::bitset<maxn> f;
int l,r,m;
LL fac[maxn],inv[maxn];
LL ans;
inline LL quick(LL a,LL b) {LL S=1;while(b) {if(b&1ll) S=S*a%mod;b>>=1ll;a=a*a%mod;}return S;}
inline LL A(int n,int m) {if(n<m) return 0;return fac[n]*inv[n-m]%mod;}
int main() {
scanf("%d%d",&l,&r);
for(re int i=l;i<=r;i++) {
if(f[i]) continue;m++;
for(re int j=i;j<=r;j+=i) f[j]=1;
}
fac[0]=1;for(re int i=1;i<=r-l+1;i++) fac[i]=(fac[i-1]*i)%mod;
inv[0]=1;inv[r-l+1]=quick(fac[r-l+1],mod-2);
for(re int i=r-l;i>=0;--i) inv[i]=(inv[i+1]*(LL)(i+1))%mod;
for(re int i=m;i<=r-l+1;i++) {
ans=(ans+A(i-1,m-1)*(LL)i%mod)%mod;
}
printf("%lld
",fac[r-l+1-m]*ans%mod*(LL)m%mod);
return 0;
}