本の選択の質問/あなたが1人なら
トピックリンク:ybt金メダルナビゲーション1-1-7 / luogu P6089
トピック
2種類のポイントがあり、最初の種類のポイントはいくつかの2番目の種類のポイントに接続され、接続された2番目の種類のポイントごとに、この最初の種類のポイントがこのポイントを選択する確率があります。そうでない場合、ジャンプします。接続されている次のポイントに移動します。次に、最後のものを選択しない場合は、最初のものにスキップして続行します。
逆ペアを期待する確率を尋ねます。
アイデア
kkで最初のポイントを見てみましょう第2種のkポイント。
次に、iiの選択を見てみましょう。i秒点の確率。
無限で非常に面倒なので、最初のポイントだけを見ていきます。
最初のラウンドで選択される確率はppですp、2回目のラウンドは(1 − p)kp(1-p)^ kp(1−p )k p、第3ラウンドは(1 − p)2 kp(1-p)^ {2k} p(1−p )2 k個のPなど。
全確率は∑ i =0∞(1 − p)ikp \ sum \ limits_ {i = 0)^ {\ infty}(1-p)^ {ik)pであることがわかります。i = 0∑∞(1−p )I k個のp。
次に、単純化する方法を見て、それが等比数列の合計であることがわかります。
次に、1(1 − qn)1 − q \ dfrac {a_1(1-q ^ n)} {1-q}に等しくなります。1−qA1(1−qN)、式は次のように変更できます
。p(1 −(1 − p)k×∞)1 −(1 − p)k \ dfrac {p(1-(1-p)^ {k \ times \ infty} )} {1-(1-p)^ k}1−(1−p )kp (1−(1−p )K × ∞)、これはp(1 −(1 − p)∞)1 −(1 − p)k \ dfrac {p(1-(1-p)^ {\ infty})){1-(1-p)^ k}1−(1−p )kp (1−(1−p )∞)
そのため、P 1-P - 11−pはゼロより大きく、1より小さい数であるため、その無限の累乗は無限にゼロに近く、1から1を引いたものは無限に1に近くなります。
次に、この式は次のようになります。p1 −(1 − p)k \ dfrac {p} {1-(1-p)^ k}1−(1−p )kP
次に、最初のポイントが選択される確率を取得し、次に2番目と3番目のポイントの確率を見つける方法を教えてください。
明らかに、これらの点が選択される確率は、前の点が選択される確率×(1 − p)\ times(1-p)であることがわかります。× (1−p )。(つまり、最後のものが選択されていない場合、これはもう一度選択されません。もう一度乗算するだけです×(1 − p)\ times(1-p)× (1−p ))
第 i i iが選択される確率はp×(1 − p)i − 1 1 −(1 − p)k \ dfrac {p \ times(1-p)^ {i-1}){1-(1- p )^ k}1−(1−p )kp××(1−p )I - 1。
高速電力を使用して電力を見つけることは明らかです。そうすれば、確率を見つけることができます。
次に、何を期待するかを見てみましょう。
タイトルに反転ペアが必要であることを確認すると、当然、反転ペアのツリー配列が考えられます。
しかし、それが望んでいるのは期待です。
通常の逆の順序では、毎回1つずつ追加してから、このポイントの確率を追加します。また、前の逆順序ペアを探すときは、このポイントが選択される確率を乗算する必要があります。
このようにして、これらの2つのポイントが選択される確率が乗算されることがわかります。これは、この逆のペアの期待値です。
次に注意すべきことの1つは、問題の精度が低下し、longdoubleを使用して問題を解決することです。
コード
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
int n, m, x, y, size;
vector <int> a[500001];
long double p, re, ans, tree[500001], thi;
void build(int x, long double y) {
//树状数组
for (int now = x; now <= 500000; now += now & (-now))
tree[now] += y;
}
long double ask(int x) {
re = 0;
for (int now = x; now; now -= now & (-now))
re = re + tree[now];
return re;
}
long double ksm(long double x, int y) {
//快速幂
re = 1.0;
while (y) {
if (y & 1) re = re * x;
x = x * x;
y >>= 1;
}
return re;
}
int main() {
scanf("%d %d", &n, &m);
scanf("%Lf", &p);
for (int i = 1; i <= m; i++) {
scanf("%d %d", &x, &y);
a[x].push_back(y);
}
for (int i = 1; i <= n; i++)
sort(a[i].begin(), a[i].end());
ans = 0.0;
for (int i = 1; i <= n; i++) {
size = a[i].size();
for (int j = 0; j < size; j++) {
thi = p * ksm(1.0 - p, j) / (1.0 - ksm(1.0 - p, size));//算出来的概率
ans += (ask(m) - ask(a[i][j])) * thi;
build(a[i][j], thi);
}
}
printf("%.2Lf", ans);
return 0;
}