Editorial for Lantern Sparks
Remember to use this editorial only when stuck, and not to copy-paste code from it. Please be respectful to the problem author and editorialist.
Submitting an official solution before solving the problem yourself is a bannable offence.
Submitting an official solution before solving the problem yourself is a bannable offence.
Approach
Let be the indicator that wire
sparks. Then
, so
.
The wires are not independent: two wires that share a lantern succeed or fail together more often than independent events would. Linearity does not need independence, so it is enough to compute each probability separately.
Lantern chooses uniformly from
. The number of multiples of
in that
interval is
. Hence the
probability that lantern
is not divisible by
is
.
Brightnesses are chosen independently, so a wire fails only if both endpoints fail:
.
Sum these contributions over all wires in
.
Solution (C++)
#include <bits/stdc++.h>
using namespace std;
const int MOD = 1000000007;
long long modpow(long long a, long long e) {
long long r = 1;
a %= MOD;
while (e) {
if (e & 1) {
r = r * a % MOD;
}
a = a * a % MOD;
e >>= 1;
}
return r;
}
long long multiples(long long l, long long r, long long p) {
return r / p - (l - 1) / p;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int n, m;
long long p;
cin >> n >> m >> p;
vector<long long> fail_num(n), fail_den(n);
for (int i = 0; i < n; i++) {
long long l, r;
cin >> l >> r;
long long len = r - l + 1;
long long good = multiples(l, r, p);
fail_num[i] = len - good;
fail_den[i] = len;
}
long long ans = 0;
for (int i = 0; i < m; i++) {
int u, v;
cin >> u >> v;
u--;
v--;
long long den = fail_den[u] % MOD * (fail_den[v] % MOD) % MOD;
long long none = fail_num[u] % MOD * (fail_num[v] % MOD) % MOD;
long long ok = (den - none) % MOD;
if (ok < 0) {
ok += MOD;
}
ans += ok * modpow(den, MOD - 2) % MOD;
if (ans >= MOD) {
ans -= MOD;
}
}
cout << ans << "\n";
}
Comments