题意:给一个区间[l,r],每次选一个数.把它和它的倍数去掉,耗时为[l,r]的所有数都被消掉的次数,求所有不同选择方案的总耗时.
分析:对于区间[3,9]来说,3,4,5,7这四个数字必须要主动去消,我们假设称这样的数字为"关键数",则对于任意一种选择方案,最后一次(主动)消去的数字一定是一个"关键数".
假设区间[l,r]内有sum个"关键数"(sum可以直接埃氏筛暴力得出).则对于任意一种选择方案,最少需要消sum次,最多需要消n(n=r-l+1)次.
假设有一类选择方案是要消i次,则这一类选择方案总耗时为(i*(sum*(i-1)!*C_{n-sum}^{n-i}*(n-i)!)),解释式子:
最后一次(第i次)消去的一定是"关键数",且是(sum)中任意一个,前(i-1)个数可以任意排列,即有((i-1)!)中排列方案,后面的(n-i)个数一定全都是"非关键数",一共有(n-sum)个"非关键数",故有(C_{n-sum}^{n-i})种选择方案,后面(n-i)个数也可以任意排列,即有((n-i)!)种选择方案.故消i次一共有(sum*(i-1)!*C_{n-sum}^{n-i}*(n-i)!)种选择方案,消i次的总耗时为(i*(sum*(i-1)!*C_{n-sum}^{n-i}*(n-i)!))
所有最后的答案就是(ans=sum_{i=sum}^{i=n}i*(sum*(i-1)!*C_{n-sum}^{n-i}*(n-i)!))
我下面的代码也是为了卡常 费尽心思了的...
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#define mod 1000000007
#define N 10000007
#define rg register
using namespace std;
inline int read(){
rg int s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();}
return s*w;
}
inline void write(int x){
if(x<0)putchar('-'),x=-x;
if(x>9)write(x/10);
putchar(x%10+'0');
}
int sum,ans,visit[N],jc[N],ny[N];
inline int ksm(int a,int b){
rg int cnt=1;
while(b){
if(b&1)cnt=1ll*cnt*a%mod;
a=1ll*a*a%mod;
b>>=1;
}
return cnt%mod;
}
inline int C(int n,int m){return n<m?0:1ll*jc[n]*ny[m]%mod*ny[n-m]%mod;}
inline void get_jc(int n){
jc[0]=1;
for(rg int i=1;i<=n;++i)jc[i]=1ll*jc[i-1]*i%mod;
ny[n]=ksm(jc[n],mod-2);
for(rg int i=n-1;i>=0;--i)ny[i]=1ll*ny[i+1]*(i+1)%mod;
return;
}
inline void get_num(int l,int r){
for(rg int i=l;i<=r;++i){
if(visit[i])continue;
sum++;
for(rg int j=i;j<=r;j+=i)visit[j]=1;
}
return;
}
int main(){
rg int l=read(),r=read(),n=r-l+1;
get_num(l,r),get_jc(r);
for(rg int i=sum;i<=n;++i){
rg int res=1ll*i*sum%mod;
res=1ll*res*jc[i-1]%mod;
res=1ll*res*jc[n-i]%mod;
res=1ll*res*C(n-sum,n-i)%mod;
ans=(ans+res)%mod;
}
write(ans);
return 0;
}