https://www.luogu.org/problemnew/show/P4562
https://www.lydsy.com/JudgeOnline/problem.php?id=5323
(BZOJ有点卡常数过不去。)时限已经开大。
实际上我们只需要求出l~r区间内有多少数是满足不存在l~r内的数a使得i*a=这个数。
我们欧拉筛实际上就是一个数可以分解成的最大的两个数(其中一个是最大质数)的乘积,于是我们判断那个合数是否<l且这个数是否在l~r的区间内,如果满足则这个数就是我们要求的。
然后数学公式导一波就行了。
#include<cmath> #include<queue> #include<cstdio> #include<cctype> #include<cstring> #include<iostream> #include<algorithm> using namespace std; typedef long long ll; const int N=1e7+5; const int p=1e9+7; int l,r,tot,su[N],cnt; ll jc[N],inv[N]; bool he[N]; int qpow(int k,int n){ int res=1; while(n){ if(n&1)res=(ll)res*k%p; k=(ll)k*k%p;n>>=1; } return res; } void Euler(int n){ for(int i=2;i<=n;++i){ if(!he[i]){ su[++tot]=i; if(l<=i&&i<=r)++cnt; } bool ok=0; for(int j=1;j<=tot;++j){ int q=i*su[j]; if(q>n)break; he[q]=1; if(l<=q&&q<=r&&i<l)++cnt; if(i%su[j]==0)break; } } } ll C(int n,int m){ return jc[n]*inv[m]%p*inv[n-m]%p; } void init(int n){ jc[0]=1; for(int i=1;i<=n;++i)jc[i]=jc[i-1]*i%p; inv[n]=qpow(jc[n],p-2); for(int i=n-1;i;i--)inv[i]=inv[i+1]*(i+1)%p; inv[0]=1; } int main(){ scanf("%d%d",&l,&r); init(r); ll ans=0; if(l==1){ for(int i=1;i<=r;++i){ ans=(ans+i*jc[r-1])%p; } printf("%lld ",ans); }else{ Euler(r); int n=r-l+1; for(int i=cnt;i<=n;++i){ ans=(ans+i*C(n-cnt,i-cnt)%p*jc[i-1]%p*jc[n-i]%p*cnt%p)%p; } printf("%lld ",ans); } return 0; }
+++++++++++++++++++++++++++++++++++++++++++
+本文作者:luyouqi233。 +
+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+
+++++++++++++++++++++++++++++++++++++++++++