运行时间超时了,但是不提示超时。
def ksm(a, b): # 快速幂 计算 a ** b
s = 1
while b:
if b & 1:
s = s * a % MOD
a = a * a % MOD
b >>= 1
return s
def cal(n, m): # 计算组合数 C n m
# 组合数C n m = n ! / (m ! * (n - m)!)
# 费马小定理:如果 p 是一个质数,那么对于任何整数 a:a ** (p - 1) = 1 mod p
# 由此推导出模逆元计算公式: a ** (-1) = a ** (p - 2) mod p
# 利用模逆元计算公式,将组合数计算中的除法转换成乘法,并避免数值溢出
if m > n - m: # 组合数的对称性
m = n - m
ans = 1
for i in range(1, m + 1):
ans = ans * (n - m + i) * ksm(i, MOD - 2) % MOD
return ans
while True:
try:
n, m, k = map(int, input().split())
num = list(map(int, input().split()))
MOD = 1000000007
# 对于一个num[i]和m,按二进制来看,num[i] & m 的最低位的1 和 num[i] 相加后,会变0进位,更低位的值不会变化
# 下一次num[i] & m 的1的最低位将会变高
# 当num[i]的1最低位比m的1最高位还高时,num[i]的值将不会发生变化
length = len(bin(m)[2:])
p = [0] * (length + 2) # num[i]的变化情况 比 m的二进制位数 多2
for i in range(length + 1): # 变化i次的概率为 C k i / 2 ** k
p[i] = cal(k, i) * ksm(ksm(2, k), MOD - 2) % MOD
p[-1] += MOD - p[i]
p[-1] = (1 + p[-1]) % MOD # 变化次数 大于 m的二进制位数 时,num[i]不变
ans = 0
for i in range(n):
for j in range(length + 2):
ans = ans + num[i] * p[j] % MOD
ans %= MOD
num[i] += num[i] & m
# 这里不能写成 num[i] = num[i] + num[i] & m , 因为 + 比 & 优先级高
print(ans)
except:
break

京公网安备 11010502036488号