[JXOI2018]游戏
题意
实在描述不来\(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\))