「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!
致虚极,守静笃,万物并作,吾以观其复