2200G. Operation Permutation
Combinatorics, dp, math, probabilities
https://codeforces.com/problemset/problem/2200/G
AksLolCoding has an integer 𝑥 and a list of 𝑛 operations. Each operation is a string starting with one of the symbols +,-,x, or /(representing addition, subtraction, multiplication, and real number division respectively), followed immediately by a positive integer 𝑦 (1≤𝑦≤109). For example, the operation x3 represents multiplying 𝑥 by 3.
AksLolCoding will randomly permute the operations and then apply all operations sequentially to 𝑥 in the permuted order. Help AksLolCoding compute the expected∗ final value of 𝑥 modulo 109+7.
Formally, let 𝑀=109+7. It can be shown that the answer can be expressed as an irreducible fraction 𝑝𝑞, where 𝑝 and 𝑞 are integers and 𝑞≢0(mod𝑀). Output the integer equal to 𝑝⋅𝑞−1(mod𝑀). In other words, output such an integer 𝑎 that 0≤𝑎<𝑀 and 𝑎⋅𝑞≡𝑝(mod𝑀).
∗The expected final value of 𝑥 is the average of the final value of 𝑥 over all 𝑛! permutations.
Input
The first line contains a single integer 𝑡 (1≤𝑡≤1000), the number of test cases.
For each test case, the first line contains two integers 𝑛 and 𝑥 (1≤𝑛≤3000, 1≤𝑥≤109).
The second line of each test case contains 𝑛 strings, each representing an operation in the format described above.
The sum of 𝑛2 over all test cases does not exceed 30002.
Note: x is used to represent multiplication, not *
Output
For each test case, output a single integer: the expected final value of 𝑥 modulo 109+7.
Example
input
4
2 10
x2 -10
4 2
+6 +7 /1 -13
8 1
+1 x2 x3 +4 +5 +6 -7 -8
9 864209753
-918273645 x564738291 /365107362 x734582911 -654321789 x998244353 +172519103 /482193765 /482091376output
5
2
166666677
601980218Note
In the first test case, 𝑥 can either be (10⋅2)−10=10 or (10−10)⋅2=0, resulting in an expected value of 5.
In the second test case, all possible permutations result in 𝑥=2.
In the third test case, the expected value of 𝑥 is 556.
【尹显齐 2500011456 物理学院】
数学基础:费马小定理
我们可以利用它求逆元:
此题中,模数
最trivial的方法的时间复杂度是
首先,我们应当意识到,本质上我们只进行
那么最终的结果一定可以表示为
注意到,在某一步加上的数
排成一个特定顺序,此时我们在这个序列中随机地插入
现在,考虑这个值对所有乘数排成的序列的平均值。序列总共有
种序列,那么如果我们能计算出所有不同方式得到的
注意到
那么答案就是对
而计算
那么
实际计算时,除以分母都采用乘以分母的逆元。这样,我们就在
MOD = 10**9+7 # 模数
N = 3000 # n最大值、
# 预计算1到3000的阶乘值
fact = [1]*(N+1)
for i in range(1,N+1):
fact[i] = fact[i-1]*i%MOD
# 主程序
for _ in range(int(input())):
n,x = map(int,input().split())
oper = input().split()
ans = 0 # 记录所有加减之和
mul = [] # 记录所有乘数
for op in oper:
a,b = op[0],int(op[1:])
if a == "+":
ans += b
elif a == "-":
ans -= b
elif a == "x":
mul.append(b)
else:# 是除法,乘以其逆元
mul.append(pow(b,MOD-2,MOD))
ans %= MOD
l = len(mul)#乘数个数
dp = [[0]*(l+1) for _ in range(l+1)]#dp计算S(k)
dp[0][0] = 1#初始化
for i in range(1,l+1):
for j in range(i+1):
dp[i][j] = (dp[i-1][j]+(dp[i-1][j-1]*mul[i-1])%MOD)%MOD
#下面过程和上方式子一一对应
mulans = 0
for i in range(l+1):
mulans += dp[l][i]*(fact[i]*fact[l-i])%MOD
mulans %= MOD
mulans *= pow(l*fact[l]%MOD,MOD-2,MOD)
mulans %= MOD
print(((x*dp[l][l])%MOD + (ans*mulans)%MOD)%MOD)