赞
踩
给你一个正整数
p
。你有一个下标从 1 开始的数组nums
,这个数组包含范围[1, 2p - 1]
内所有整数的二进制形式(两端都 包含)。你可以进行以下操作 任意 次:
- 从
nums
中选择两个元素x
和y
。- 选择
x
中的一位与y
对应位置的位交换。对应位置指的是两个整数 相同位置 的二进制位。比方说,如果
x = 1101
且y = 0011
,交换右边数起第2
位后,我们得到x = 1111
和y = 0001
。请你算出进行以上操作 任意次 以后,
nums
能得到的 最小非零 乘积。将乘积对109 + 7
取余 后返回。注意:答案应为取余 之前 的最小值。
- class Solution {
- public:
- typedef long long LL;
- LL mod = 1e9 + 7;
- LL qp(LL a, LL b){
- a %= mod;
- LL ret = 1;
- while(b){
- if(b & 1) ret = ret * a % mod;
- b >>= 1, a = a * a % mod;
- }
- return ret;
- }
- int minNonZeroProduct(LL p) {
- LL k = (1LL << p) - 1;
- return k % mod * qp(k - 1, k >> 1) % mod;
- }
- };
任给两个数a,b,不妨设a < b,a给b1是否能让a * b变小呢?
我们不妨设a = x + 2 ^ k,b = y,(y的第k位为0)
那么交换前有a * b = xy + y * 2 ^ k
交换后a = x,b = y + 2 ^ k,a *b = xy + x * 2 ^ k
由于x < y,所以结果变小
然后对于[1, 2 ^ p - 1]这2 ^ p - 1个数字,我们可以分为[1, 2 ^ (p - 1) - 1],[2 ^ (p - 1), 2 ^ p - 2],2 ^ p - 1
我们发现[1, 2 ^ (p - 1) - 1],[2 ^ (p - 1), 2 ^ p - 2]可以配成偶数对没有相同1的数对,而且两两相加为2 ^ p - 1
如p = 3,则可分为[1, 2, 3]、[4, 5, 6]、7
1 + 6 = 7,2 + 5 = 7,3 + 4 = 7,左边区间可以将除最低位1外的所有1都给右边,于是得到
1,1,1,6,6,6,7
不难证明左边区间保留最低位1时比保留其它位1更优
于是给定p,我们的答案就是 (2 ^ p - 1) * pow(2 ^ p - 2, 2 ^ (p - 1) - 1)
时间复杂度:O(p) 空间复杂度:O(1)
- class Solution {
- public:
- typedef long long LL;
- LL mod = 1e9 + 7;
- LL qp(LL a, LL b){
- a %= mod;
- LL ret = 1;
- while(b){
- if(b & 1) ret = ret * a % mod;
- b >>= 1, a = a * a % mod;
- }
- return ret;
- }
- int minNonZeroProduct(LL p) {
- LL k = (1LL << p) - 1;
- return k % mod * qp(k - 1, k >> 1) % mod;
- }
- };
- class Solution:
- def minNonZeroProduct(self, p: int) -> int:
- MOD = 1_000_000_007
- k = (1 << p) - 1
- return k * pow(k - 1, k >> 1, MOD) % MOD
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。