快速幂(技巧版)+ 一点点数学推理

首先还是简单说一下这个题目描述:
给你一个正整数 p 。你有一个下标从 1 开始的数组 nums ,这个数组包含范围 [1, 2^p - 1] 内所有整数的二进制形式(两端都 包含)。你可以进行以下操作 任意 次:
从 nums 中选择两个元素 x 和 y 。
选择 x 中的一位与 y 对应位置的位交换。对应位置指的是两个整数相同位置的二进制位。
比方说,如果 x = 1101 且 y = 0011 ,交换右边数起第 2 位后,我们得到 x = 1111 和 y = 0001 。

请你算出进行以上操作任意次以后,nums 能得到的最小非零乘积。将乘积对 10^9 + 7 取余后返回。

注意:答案应为取余之前的最小值。

示例 1:
输入:p = 1
输出:1
解释:nums = [1] 。
只有一个元素,所以乘积为该元素。

示例 2:
输入:p = 2
输出:6
解释:nums = [01, 10, 11] 。
所有交换要么使乘积变为 0 ,要么乘积与初始乘积相同。
所以,数组乘积 1 * 2 * 3 = 6 已经是最小值。

示例 3:
输入:p = 3
输出:1512
解释:nums = [001, 010, 011, 100, 101, 110, 111]

  • 第一次操作中,我们交换第二个和第五个元素最左边的数位。
    • 结果数组为 [001, 110, 011, 100, 001, 110, 111] 。
  • 第二次操作中,我们交换第三个和第四个元素中间的数位。
    • 结果数组为 [001, 110, 001, 110, 001, 110, 111] 。
      数组乘积 1 * 6 * 1 * 6 * 1 * 6 * 7 = 1512 是最小乘积。

注意:1 <= p <= 60
其实这题目大家乍一看可能不知道从何下手,但是我们一看那个样例输入,还有题目描述的例子,我们可以发现一个规律就是他的目标就是尽可能多的去构造这个1和另外一个数相乘(具体原理大家可以参考leetcode灵神题解数学证明,很多时候都是玄学直观感觉就是对的,可以大胆尝试着提交一下),而且我们可以看到最明显的就是p=3的时候的构造,我们可以发现一个非常明显的特征,那就是除了最后一个7(也就是 2^p - 1),其他的构造都是1*6(这个6也就是(2^p - 2) 其实如果这里大家还不是很确定这个规律,我们自己在本子上在看一下p=4的情况 我们来简单看一下 这里以0010和1101为例,这两个数字就类比我们上面的正数第二个数字和倒数第三个数字的交换构造,可以得到交换后的结果为 1110 和 0001也就是我们上面得到的 (2^p - 2 和 1)推理到这里大家就可以大胆猜想这题的答案其实就是若干个(2p-2)相乘和(2p-1)在相乘即可得到结果,那么至于这个若干个n是多少呢?
这里其实很好分析,大家看那个p=3的例子就可以看到,其实也就是去掉了最后一个数(2p-1)然后两两个数字构成一对去构造,所以这个n实际上就是(2p-2)/2对数字,也就是最终结果我们可以得到结果为: ( 2 p − 1 ) ⋅ ( 2 p − 2 ) 2 p − 1 − 1 (2^p-1)\cdot(2^p-2)^{2^{p-1}-1} (2p1)(2p2)2p11

这里由于幂次太高,所以需要快速幂poww(x,p)
这里大家可以修改一下快速幂的使用技巧,由于我们的幂次是(2^(p-1) - 1)也就是
p-1个1组成的二进制数字,所以我们可以省去判断 p&1的步骤,因为每一步都是1
例如3&1=1,1&1=1…得到最终的代码为:

class Solution {
public:
    const int mod = 1e9 + 7;
    typedef long long ll;
    long long poww(long long x ,int p){
        x %= mod;
        long long res = 1;
        while(p--){//p个1的二进制数求快速幂就可以这么做,当然你写正常版本的快速幂也没有问题
            res = res * x % mod;
            x = x * x % mod;
        }
        return res % mod;
    }
    int minNonZeroProduct(int p) {
        long long  k = (1ll << p) - 1;
        return k % mod * poww(k - 1, p - 1) % mod;
    }
};

相关推荐

  1. 快速技巧)+ 点点数学推理

    2024-03-21 17:44:02       20 阅读
  2. 【算法】数论---快速

    2024-03-21 17:44:02       42 阅读
  3. 数论】矩阵快速

    2024-03-21 17:44:02       30 阅读
  4. 蓝桥杯每日题:转圈游戏(快速

    2024-03-21 17:44:02       17 阅读
  5. 蓝桥杯每日题(快速、组合计数)

    2024-03-21 17:44:02       16 阅读
  6. 快速 FastPower

    2024-03-21 17:44:02       45 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-03-21 17:44:02       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-21 17:44:02       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-21 17:44:02       19 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-21 17:44:02       20 阅读

热门阅读

  1. QRandomGenerator生成随机数

    2024-03-21 17:44:02       19 阅读
  2. ubuntu Docker无法使用zip unzip指令 解决方案 服务器

    2024-03-21 17:44:02       22 阅读
  3. 数据按设定单位(分辨率)划分的方法

    2024-03-21 17:44:02       20 阅读
  4. spring boot 如何升级 Tomcat 版本

    2024-03-21 17:44:02       21 阅读
  5. 什么是网站的外联机制?

    2024-03-21 17:44:02       20 阅读
  6. docker 常用命令

    2024-03-21 17:44:02       21 阅读
  7. 算法刷题day34:并查集

    2024-03-21 17:44:02       22 阅读