[JXOI2018] 游戏
一道概率与期望(统计与组合)的题目,一位组合蒟蒻来见识一下自己有多弱。
明显的,我们可以把一些必须选完这些数才可以完成任务的数,这里成为假素数。
可以埃筛筛出假素数的数量 k 可以枚举最后一个被选中的假素数的位置 \(i\) 其他的 \(k-1\) 可以在 \(i-1\) 个数中选择一个方案为 \(A_{k-1}^{i-1}\) 而其他的数随便放,方案为 \((n-k)!\), 所以贡献为 \(i \times A_{k-1}^{i-1} \times (n-k)!\) ,注意这里的组合数需要用逆元前缀来算,不然超时。
当然有一种更加简单的方法,直接算 \(t(p)\) 的期望,再乘上 \(n!\) 即可。这个期望也很简单,我们知道期望是线性的,这样的话就可直接把每一个决策的期望求和即可,这里的决策就是我们放的非假素数,我们已知每一个假素数的位置,就是每一个黑球,而我们的每一个白球就是每一个非假素数,可以插入的空间就是每一个假素数的中间和两边,共 \(k+1\) 个空格,而其中有 \(k/(k+1)\) 的概率会对总的期望有所贡献,所以期望就是 \(k+(n-k)*k/(k+1)\) ,即 \((n+1)/(k+1)\) ,所以总答案就是 \(n!*(n+1)/(k+1)=(n+1)!/(k+1)\) 。
first .method code
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod=1e9+7;
int ans=1,l,r,k,n,vis[10000005];
int pre[10000005];
int mul[10000005],imul[10000005],inv[10000005];
int qpow(int x,int y){
int res=1;
while(y){
if(y&1)res*=x,res%=mod;
x*=x,x%=mod;
y>>=1;
}
return res;
}
signed main(){
scanf("%lld%lld",&l,&r);
n=r-l+1;
for(int i=l;i<=r;i++){
if(vis[i])continue;
k++;
for(int j=i;j<=r;j+=i)vis[j]=1;
}
ans=0;
pre[0]=1;
for(int i=1;i<=n;i++)
pre[i]=pre[i-1]*i,pre[i]%=mod;
imul[n]=qpow(pre[n],mod-2);
for(int i=n-1;~i;i--)imul[i]=imul[i+1]*(i+1)%mod;
for(int i=k;i<=n;i++){
ans+=pre[i-1]*imul[k-1]%mod*imul[i-k]%mod*pre[k]%mod*pre[n-k]%mod*i%mod;
//cout<<ans<<endl;
ans%=mod;
}
cout<<ans;
return 0;
}
second.method code
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod=1e9+7;
int ans;
int l,r;
int a[10];
bool vis[10000005];
int k,n;
signed main(){
scanf("%lld%lld",&l,&r);
if(l==1){
ans=1;
int p=(1+r)*r/2;p%=mod;
for(int i=1;i<=r-1;i++)
ans *= i,ans%=mod;
cout<<ans*p%mod<<endl;
return 0;
}
n=r-l+1;
for(int i=l;i<=r;i++){
if(vis[i])continue;
k++;
for(int j=i;j<=r;j+=i)vis[j]=1;
}
ans=1;
for(int i=1;i<=n+1;i++){
if(i==k+1)continue;
ans*=i,ans%=mod;
}
ans*=k;
ans%=mod;
cout<<ans;
// k/(k+1) * (n+1)!
return 0;
}

浙公网安备 33010602011771号