题意
实在描述不来(orz)
[JXOI2018]游戏
想法
我们考虑用筛法,把([l,r])之间的质数全部标记起来,那么就有(sum)个质数,这些质数是都要被巡一遍的
我们考虑(f(i))为最后一个质数被检查在(i)时刻的方案数
那么有(f(i) = (i - 1)! * A(n - sum,n - i) * sum)
作为最后一个质数有(sum)种,前(i - 1)个数排列,然后后(n - i)个数是随意的
代码
#include<iostream>
#include<cstdio>
#define ll long long
ll l,r;
ll mod = 1e9 + 7,cnt;
bool vis[10000005];
void sieve(){
for(int i = l;i <= r;++i){
if(!vis[i]){
++cnt;
for(int j = 1;j * i <= r;++j)
vis[j * i] = 1;
}
}
}
ll ans,n,fac[10000005],inv[10000005];
ll qpow(ll a,ll b){
ll ans = 1;
while(b){
if(b & 1) ans = 1ll * ans * a % mod;
a = 1ll * a * a % mod;
b >>= 1;
}
return ans;
}
ll A(ll n,ll m){return 1ll * fac[n] * inv[n - m] % mod;}
ll f(ll now){return 1ll * fac[now - 1] * cnt %mod * A(n - cnt,n - now) % mod;}
int main(){
scanf("%lld%lld",&l,&r);
sieve();
n = r - l + 1;
fac[0] = 1;
//std::cout<<cnt<<std::endl;
for(int i = 1;i <= r;++i)
fac[i] = 1ll * fac[i - 1] * i % mod;
//puts("");
inv[r] = qpow(fac[r],mod - 2);
for(int i = r - 1;i >= 0;--i)
inv[i] = 1ll * inv[i + 1] * (i + 1) % mod;
for(int i = cnt;i <= n;++i)
ans = ans + i * f(i) % mod;
std::cout<<ans % mod;
}
(不要忘记最后答案取膜 求(inv)要求到(0))