Search for a command to run...
Progressive hints first, then the full explanation and implementation when you're ready to cash out.
Review status
AI-generated and still unreviewed. Double-check the details before internalizing them.
Hints
Open only as much as you need to keep the solve alive.
Turn every operation into either an additive constant or a multiplicative factor: -y is adding , and /y is multiplying by modulo .
The original is boring in a good way: no matter the permutation, it gets multiplied by every multiplicative operation exactly once.
For one additive operation with value , its final contribution is times the product of the multiplicative operations that appear after it.
Other additive operations do not affect that product, so for one fixed additive operation, only its relative order among the multiplicative operations matters.
If is the elementary symmetric sum of degree over all multiplicative factors, then the expected multiplier after any additive operation is Compute the values with polynomial DP.
I checked the official Codeforces editorial and accepted-submission listings first. The intended route is exactly: normalize operations, use linearity of expectation, compute elementary symmetric sums with DP, then average over the relative position of one additive operation. Sources: official editorial, accepted submission listing.
Rewrite the operations into two kinds:
+y gives an additive value ;-y gives an additive value ;xy gives a multiplicative factor ;/y gives a multiplicative factor modulo .Let the multiplicative factors be
and let the sum of all additive values be
The starting value always contributes
because every multiplicative operation eventually hits it, regardless of order.
Now take one additive operation with value . In a fixed permutation, once is added, only the multiplicative operations after it can change it. Its contribution is
By linearity of expectation, all additive operations can share the same expected multiplier. Their actual values only matter through . Nice little probability coupon, no need to wrestle all permutations like a maniac.
For one fixed additive operation, ignore every other additive operation. They do not affect the product. So we only care about the relative order of these objects:
The rank of among them is uniform. Therefore the number of multiplicative operations after is uniform over , with probability
Conditioned on exactly multiplicative operations being after , the subset is uniformly random among all subsets.
Define as the elementary symmetric sum of degree :
Then the average product of a random size- subset is
So the expected multiplier applied to any additive operation is
The final answer is
To compute the values, use the generating polynomial
Its coefficient of is . Standard descending DP:
and for every factor ,
After processing all factors, .
For the binomial denominator,
Precompute factorials and inverse factorials modulo .
Edge cases:
/1 and x1 are fine as factors equal to ; keeping them in the DP is correct.Complexity:
per test case and memory. Since and the statement gives
this fits easily.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
const ll MOD = 1000000007LL;
const int MAXN = 3005;
ll modPow(ll a, ll e) {
ll r = 1;
while (e > 0) {
if (e & 1) r = r * a % MOD;
a = a * a % MOD;
e >>= 1;
}
return r;
}
ll inv(ll x) {
return modPow(x, MOD - 2);
}
int main() {
setIO();
vector<ll> fact(MAXN), invFact(MAXN), invNum(MAXN);
fact[0] = 1;
for (int i = 1; i < MAXN; i++) fact[i] = fact[i - 1] * i % MOD;
invFact[MAXN - 1] = inv(fact[MAXN - 1]);
for (int i = MAXN - 2; i >= 0; i--) invFact[i] = invFact[i + 1] * (i + 1) % MOD;
for (int i = 1; i < MAXN; i++) invNum[i] = inv(i);
int T;
cin >> T;
while (T--) {
int n;
ll x;
cin >> n >> x;
vector<ll> mults;
ll addSum = 0;
ll base = x % MOD;
for (int i = 0; i < n; i++) {
string op;
cin >> op;
char c = op[0];
ll y = stoll(op.substr(1)) % MOD;
if (c == '+') {
addSum = (addSum + y) % MOD;
} else if (c == '-') {
addSum = (addSum - y + MOD) % MOD;
} else {
ll a = (c == 'x' ? y : inv(y));
mults.push_back(a);
base = base * a % MOD;
}
}
int m = (int)mults.size();
vector<ll> dp(m + 1);
dp[0] = 1;
int deg = 0;
for (ll a : mults) {
deg++;
for (int k = deg; k >= 1; k--) {
dp[k] = (dp[k] + dp[k - 1] * a) % MOD;
}
}
ll expectedMultiplier = 0;
for (int k = 0; k <= m; k++) {
ll invChoose = fact[k] * fact[m - k] % MOD * invFact[m] % MOD;
expectedMultiplier = (expectedMultiplier + dp[k] * invChoose) % MOD;
}
expectedMultiplier = expectedMultiplier * invNum[m + 1] % MOD;
ll ans = (base + addSum * expectedMultiplier) % MOD;
cout << ans << '\n';
}
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
const ll MOD = 1000000007LL;
const int MAXN = 3005;
ll modPow(ll a, ll e) {
ll r = 1;
while (e > 0) {
if (e & 1) r = r * a % MOD;
a = a * a % MOD;
e >>= 1;
}
return r;
}
ll inv(ll x) {
return modPow(x, MOD - 2);
}
int main() {
setIO();
vector<ll> fact(MAXN), invFact(MAXN), invNum(MAXN);
fact[0] = 1;
for (int i = 1; i < MAXN; i++) fact[i] = fact[i - 1] * i % MOD;
invFact[MAXN - 1] = inv(fact[MAXN - 1]);
for (int i = MAXN - 2; i >= 0; i--) invFact[i] = invFact[i + 1] * (i + 1) % MOD;
for (int i = 1; i < MAXN; i++) invNum[i] = inv(i);
int T;
cin >> T;
while (T--) {
int n;
ll x;
cin >> n >> x;
vector<ll> mults;
ll addSum = 0;
ll base = x % MOD;
for (int i = 0; i < n; i++) {
string op;
cin >> op;
char c = op[0];
ll y = stoll(op.substr(1)) % MOD;
if (c == '+') {
addSum = (addSum + y) % MOD;
} else if (c == '-') {
addSum = (addSum - y + MOD) % MOD;
} else {
ll a = (c == 'x' ? y : inv(y));
mults.push_back(a);
base = base * a % MOD;
}
}
int m = (int)mults.size();
vector<ll> dp(m + 1);
dp[0] = 1;
int deg = 0;
for (ll a : mults) {
deg++;
for (int k = deg; k >= 1; k--) {
dp[k] = (dp[k] + dp[k - 1] * a) % MOD;
}
}
ll expectedMultiplier = 0;
for (int k = 0; k <= m; k++) {
ll invChoose = fact[k] * fact[m - k] % MOD * invFact[m] % MOD;
expectedMultiplier = (expectedMultiplier + dp[k] * invChoose) % MOD;
}
expectedMultiplier = expectedMultiplier * invNum[m + 1] % MOD;
ll ans = (base + addSum * expectedMultiplier) % MOD;
cout << ans << '\n';
}
}