目录
一.题目原型:
二思路解析:
三.代码实现:
一.题目原型:
二思路解析:
灵神的做法非常让人惊叹:
理解就是,如果一个数大于另一个数要交换的1的权重,那么他们的乘积就变小。
那么一个大的数不断变大,小的数不断变小,乘积不也就越来越小吗?
在看个例子。
注意点一:交换后所有数字的和不变,因为只是某一个数 +2^k,另一个数 -2^k,和不变.
注意点二:然后在和不变的基础上,差大积小,假如能形成 1 1 1 1 1 …… 1 n,那肯定积最小,但是,这种情况是达咩的,这就是注意点二:交换是交换,上限不会超过2^p-1,数字的上限已经决定了
回头看示例3:
注意点3:接着继续考虑,尽可能的形成1这个思路没错了,问题是最多有多少个1可以形成,接着我看示例3:我先是疑惑了一下,为什么是 1 1 1 6 6 6 7呢,和不变的情况下,差大积小,为什么不是 1 1 1 5 6 7 7呢,明显积更小啊,之后就被我发现了注意点三:在二进制位上的0、1数量是相对不变的,p=3举例,每个二进制位上都是4个1,3个0;p=4的时候 都是8个1,7个0
最关键的是:
很完美的思路:灵神太厉害了!
快速幂的知识总结下来就是一句话:x的n次方就是不断缩小n,扩大x的时候找出所有奇次方底数的积,还有本题数字太大,也需要将快速幂的模的方法搬过来。
三.代码实现:
class Solution {
const int mod = 1'000'000'007;
long long pow(long long x, long long m) {
x %= mod;
long long res = 1;
while (m>0) {
if(m&1){
res = res * x % mod;
}
m>>=1;
x = (x%mod * x % mod)%mod;
}
return res;
}
public:
int minNonZeroProduct(int p) {
long long k = (1LL << p) - 1; //k=2^p -1
long long m=(1LL<<(p-1))-1;
return k % mod * pow(k - 1, m) % mod;
}
};