「JXOI2018」游戏

传送门

Solution

枚举\(t(p)\)即可,发现\(t(p)\)的排列中最后一个满足在\([l,R]\)中无因数的数的位置

先算出这样的数有多少个(我是用线筛算的),然后组合数就好了


Code 

#include<bits/stdc++.h>
#define ll long long
#define dbg1(x) cerr<<#x<<"="<<(x)<<" "
#define dbg2(x) cerr<<#x<<"="<<(x)<<"\n"
#define dbg3(x) cerr<<#x<<"\n"
using namespace std;
#define reg register
const int MN=1e7+5,P=1e9+7;
int Mul(int x,int y){return (1ll*x*y)%P;}
int Add(int x,int y){return (x+y)%P;}
int L,R,fac[MN],inv[MN],m[MN],pr[MN],tot,N,ans;
int C(int x,int y){return Mul(fac[x],Mul(inv[y],inv[x-y]));}
int main()
{
	scanf("%d%d",&L,&R);reg int i,j;
	for(fac[0]=i=1;i<=R;++i)fac[i]=Mul(fac[i-1],i);
	if(L==1)return 0*printf("%d\n",Mul((1ll*(R-L+1)*(R-L+2)/2)%P,fac[R-L]));
	for(inv[0]=inv[1]=1,i=2;i<=R;++i)inv[i]=Mul(inv[P%i],(P-P/i));
	for(i=1;i<=R;++i)inv[i]=Mul(inv[i-1],inv[i]);
	m[1]=1;
	for(i=2;i<=R;++i)
	{
		if(!m[i])pr[++tot]=i,m[i]=1;
		for(j=1;j<=tot&&1ll*pr[j]*i<=R;++j)
		{
			m[pr[j]*i]=pr[j];
			if(pr[j]%i==0)break;
		}
	}
	for(i=L;i<=R;++i)if(m[i]==1||i/m[i]<L)++N;
	for(i=L+N-1;i<=R;++i)ans=Add(ans,Mul(i-L+1,C(i-L,N-1)));
	return 0*printf("%d\n",Mul(ans,Mul(fac[N],fac[R-L+1-N])));
}


Blog来自PaperCloud,未经允许,请勿转载,TKS!

posted @ 2019-10-12 23:06  PaperCloud  阅读(165)  评论(0编辑  收藏  举报