kuoying 2020-05-01
LINK:游戏
当L==1的时候 容易想到 答案和1的位置有关。
枚举1的位置 那么剩下的方案为(R-1)! 那么总答案为 (R+1)*R/2(R-1)!
考虑L==2的时候 对于一个排列什么时候会终止 容易发现是L~R中所有的质数 在这个排列中的最后一个位置的影响。
还是枚举这个质数的位置i 此时方案数为 C(i-1,s-1)s!(n-s)!
其中s为L~R之中所有的质数个数.
对于L>2 还是考虑先计算出s的个数 刚才是使用了线性筛 此时考虑 质数不能用了 那么可以考虑每个数是否为必要的数。
那么我们从前往后推 只需要知道离自己最近的数是谁 看一下上一个是不是就能判断当前了。
可以发现要除以一下自己的最小质因子。所以线性筛可以解决。
当然可以直接埃拉筛。统计没被筛到的数字个数即可。复杂度nloglogn
这里使用前者.
const int MAXN=10000010,maxn=110,G=3; int fac[MAXN],inv[MAXN]; int v[MAXN],p[MAXN]; int L,R; int cnt,top; inline int ksm(int b,int p) { int cnt=1; while(p) { if(p&1)cnt=(ll)cnt*b%mod; b=(ll)b*b%mod;p=p>>1; } return cnt; } inline void prepare() { fac[0]=fac[1]=1; rep(2,R,i) { fac[i]=(ll)fac[i-1]*i%mod; if(!v[i]) { v[i]=i; p[++top]=i; if(i>=L)++cnt; } rep(1,top,j) { if(p[j]>R/i)break; int ww=i*p[j]; v[ww]=p[j]; if(i<L&&ww>=L)++cnt; if(v[i]==p[j])break; } } } inline int C(int a,int b){if(a<b)return 0;return (ll)fac[a]*inv[b]%mod*inv[a-b]%mod;} int main() { freopen("1.in","r",stdin); get(L);get(R); prepare(); if(L==1)put((ll)(1+R)*R/2%mod*fac[R-1]%mod); else { inv[R]=ksm(fac[R],mod-2); fep(R-1,0,i)inv[i]=(ll)inv[i+1]*(i+1)%mod; int n=R-L+1; int ans=0; rep(cnt,n,i)ans=(ans+(ll)C(i-1,cnt-1)*fac[cnt]%mod*fac[n-cnt]%mod*i%mod)%mod; put(ans); } return 0; }