Luogu P4562 [JXOI2018]游戏

题目
我们用埃氏筛从\(l,r\)筛一遍,每次把没有被筛掉的数的倍数筛掉。
易知最后剩下来的数(这个集合记为\(S\))的个数就是我们需要选的数,设有\(s\)个,令\(n=r-l+1\)
\(f_i\)为第\(i\)次操作筛完的方案数,我们要求的就是\(\sum\limits_{i=s}^n if_i\)
枚举最后一次操作,方案数为\(s\)
后面的位置从任选不属于\(S\)的数的方案数为\(n-s\choose n-i\)
前面\(i-1\)个数是哪些就确定了,排列方案数为\((i-1)!\)
后面的同理\((n-i)!\)
所以\(f_i=s{n-s\choose n-i}(i-1)!(n-i)!\)
答案\(ans=\sum\limits_{i=s}^n if_i=s\sum\limits_{i=s}^n{n-s\choose n-i}i!(n-i)!=s(n-s)!\sum\limits_{i=s}^n\frac{i!}{(i-s)!}\)

#include<bits/stdc++.h>
using namespace std;
const int N=10000007,P=1000000007;
bitset<N>t;int fac[N],ifac[N];
int inc(int a,int b){a+=b;return a>=P? a-P:a;}
int mul(int a,int b){return 1ll*a*b%P;}
int power(int a,int k=P-2){int r=1;for(;k;k>>=1,a=mul(a,a))if(k&1)r=mul(a,r);return r;}
int main()
{
    int i,j,l,r,s=0,ans=0,n;scanf("%d%d",&l,&r),n=r-l+1;
    for(i=l;i<=r;++i) if(!t[i]) for(++s,j=i;j<=r;j+=i) t[j]=1;
    for(fac[0]=i=1;i<=r;++i) fac[i]=mul(i,fac[i-1]);
    for(ifac[r]=power(fac[r]),i=r;i;--i) ifac[i-1]=mul(i,ifac[i]);
    for(i=s;i<=n;++i) ans=inc(ans,mul(fac[i],ifac[i-s]));
    return !printf("%d",mul(mul(s,ans),fac[n-s]));
}

posted @ 2019-10-12 10:40  Shiina_Mashiro  阅读(99)  评论(0)    收藏  举报