【BZOJ5323】[JXOI2018]游戏(组合计数,线性筛)
【BZOJ5323】[JXOI2018]游戏(组合计数,线性筛)
题面
题解
显然要考虑的位置只有那些在\([l,r]\)中不存在任意一个约数的数。
假设这样的数有\(x\)个,那么剩下的数有\(n-x\)个。
枚举时间\(t\),那么强制在\(t\)时刻放下\(x\)数中的最后一个,
那么这样子的方案数就是\(\displaystyle {t-1\choose x-1}*x!*(n-x)!\)。
预处理阶乘和逆元就很好做了。
#include<iostream>
#include<cstdio>
using namespace std;
#define MOD 1000000007
#define MAX 10000001
bool vis[MAX];
int jc[MAX],jv[MAX],l,r,n,x,ans;
int main()
{
scanf("%d%d",&l,&r);n=r-l+1;
for(int i=l;i<=r;++i)
if(!vis[i]){++x;for(int j=i;j<=r;j+=i)vis[j]=true;}
jc[0]=jv[0]=jv[1]=1;
for(int i=2;i<=n;++i)jv[i]=1ll*jv[MOD%i]*(MOD-MOD/i)%MOD;
for(int i=1;i<=n;++i)jc[i]=1ll*jc[i-1]*i%MOD;
for(int i=1;i<=n;++i)jv[i]=1ll*jv[i-1]*jv[i]%MOD;
for(int i=x;i<=n;++i)ans=(ans+1ll*jc[i]%MOD*jv[i-x])%MOD;
ans=1ll*ans*x%MOD*jc[n-x]%MOD;printf("%d\n",ans);
return 0;
}