题目
题目描述
有一个a数组,我们已知他的长度为n,a[+]的和为m,请问如果我们想要a[⊕]的值最大,数组a在满足a[+]=m时有多少种情况
我们定义a[+]指
a
1
+
a
2
.
.
.
.
a
n
a_1+a_2....a_n
a1+a2....an的值,所以a[⊕]指
a
1
⊕
a
2
⊕
a
3
.
.
.
.
a
n
a_1⊕a_2⊕a_3....a_n
a1⊕a2⊕a3....an的值
其中a数组全部都为非负整数。
答案对1e9+7取模
输入描述
输入两个整数 1 ≤ n ≤ 1 0 18 1\leq n \leq 10^{18} 1≤n≤1018, 0 ≤ m ≤ 1 0 18 0\leq m \leq 10^{18} 0≤m≤1018
输出描述
输出一个整数表示方案数
题解
def main():
MOD = int(1e9 + 7)
n,m = map(int,input().split())
n %= MOD
res = 1
while m:
if m & 1: res = res * n % MOD
m >>= 1
print(res)
if __name__ == '__main__':
main()
这道题代码像是脑筋急转弯,代码非常短,但是可能会被绕进去。
假设输入
n
=
4
n = 4
n=4,
m
=
14
m = 14
m=14。
那么m的二进制表示为1110。
如果要使
a
[
⊕
]
a[⊕]
a[⊕]尽可能大,那么最好的选择就是使二进制位上的一不会被抵消为0,也就是说,确保
a
[
⊕
]
a[⊕]
a[⊕]的结果为m
,便是想要的方案。
例如,对于
m
=
14
m = 14
m=14,二进制为1110。
可以划分为:
- 1110 + 0 + 0 + 0
- 1100 + 10 + 0 + 0
- 1010 + 100 + 0 + 0
- 110 + 1000 + 0 + 0
- 1000 + 100 + 10 + 0
以上五种情况的全排列方案数的总和。
而这里的错误解题方向便是通过排列组合计算推出公式,计算出结果。
因为这道题的数据范围实在太大,所以这个方法很难行得通。
而通过进一步的观察,这个里实际上可以以非排列组合的方式更加巧妙地推出公式。
如下。
可以发现,二进制数m
中“1”的数量和每一个方案中“1”的数量是完全一致的。
而每一个方案之间的差别仅仅是"1"的位置的差别。
并且,每一位“1”可以相互独立,互不影响,像一个个独立的人一样,可以自由地选择去到任意一间房间。
因此可以把问题进一步转化如下。
如图,有 x x x个人,和n间房间,一间房间可以容纳任意数量的人。现在每一个任意去一间房间,有多少种进入房间的方案?
注:其中的x对应的便是原题中 m m m的二进制数中“1”的数量。
于是本题就不言而喻了。
原创不易,感谢支持。