题目:HDU6574
题意:在[1,n]的区间内随机等概率的找到一个r点,之后在[1,r]区间随机等概率的找到一个l点,作为区间[l,r],(都是正整数的点),问两次操作,两个区间相交的概率。
细节处理不到位就麻烦的很。一开始通过确定第一个区间进行概率计算,排除不可能的概率乘上第一个区间的概率,但是两边的不可能概率需要排列组合掉到牛角尖里了。
逆着算麻烦就正着分析吧。
先分情况考虑,首先肯定确定都是正整数,不需要积分了。由于考虑完整的一个区间十分麻烦,我们先考虑两个区间的右端点,等于是随机取两个点。但是存在相等的情况,我们先考虑进去。设第一次取的为i,第二次的为j,当i<=j时,可以得知
1
n
2
∑
i
=
1
n
∑
j
=
i
n
i
j
\frac{1}{n^2}\sum_{i=1}^{n}\sum_{j=i}^n\frac{i}{j}
n21∑i=1n∑j=inji;
当i>=j时概率
1
n
2
∑
i
=
1
n
∑
j
=
1
i
j
i
=
n
+
3
4
∗
n
\frac{1}{n^2}\sum_{i=1}^{n}\sum_{j=1}^i\frac{j}{i}=\frac{n+3}{4*n}
n21∑i=1n∑j=1iij=4∗nn+3;
但是两种情况结合显然i=j的时候被重复计算了两次,减去其概率即可
∑
i
=
1
n
1
n
2
=
1
n
\sum_{i=1}^n\frac{1}{n^2}=\frac{1}{n}
∑i=1nn21=n1。
第一种情况预处理。
#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<istream>
#include<vector>
#include<stack>
#include<set>
#include<map>
#include<algorithm>
#include<queue>
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3f
using namespace std;
typedef long long ll;
typedef double lld;
typedef pair<ll,ll> PP;
const ll mod=1000000007;
const int MAXN=4e6+5;
ll quickpow(ll a,ll n) {
ll res=1;
while(n) {
if(n&1) {
res=(res*a)%mod;
}
n>>=1;
a=(a*a)%mod;
}
return res%mod;
}
ll inv[4000100];
ll sum[4000100];
int main() {
ll n;
sum[0]=0;
scanf("%lld",&n);
for(ll i=1;i<=n*4;++i) {
inv[i]=quickpow(i,mod-2)%mod;
sum[i]=(sum[i-1]+inv[i])%mod;
}
inv[0]=quickpow((n*n)%mod,mod-2);
ll temp=(n+3)%mod;
temp=(temp*inv[4*n])%mod;
ll ans=0;
for(ll i=1;i<=n;++i) {
ll hh=sum[n]-sum[i-1];
hh=(hh*(i))%mod;
hh=(hh*inv[0])%mod;
temp=(temp+hh)%mod;
}
temp=((temp-inv[n])%mod+mod)%mod;
printf("%lld\n",temp);
return 0;
}