CF1514B AND 0, Sum Big

题目大意

给定 $n, k$,你需要建立一个 $n$ 个元素的序列 $s$,使其有 $\forall 0\le i\lt n, \exists s_i \in [0, 2^k)$; $s$ 中所有元素进行与运算的值为 $0$,并且使 $\sum_{i=0}^{n - 1}s_i$ 最大。求有多少种不同序列。

解题思路

将 $s_i$ 转换为二进制,因为使 $s$ 中所有元素进行与运算的值为 $0$,且 $\sum_{i=0}^{n - 1}s_i$ 最大,所以每个数字只有 $1$ 位上为 $0$,其他都为 $1$,且 $0$ 的出现位置互不相同。那么这题就转换成了排列组合问题。每种 $0$ 都有 $n$ 种选法,所以不难看出,答案即为 $n^k$。

主要算法

本题主要算法:幂运算

因为 $k\le 20$,所以我们可以从对 $1$ 乘 $k$ 次 $n$,就可以得到 $n^k$:

int power(int base, int freq, int mod) {
    int ans = 1;
    for (int i = 0; i < freq; i++) {
        ans *= base;
        ans %= mod;
    }
    return ans;
}

时间复杂度:$O(k)$。


这里重点介绍的是:快速幂

我们知道,乘方运算有结合律,即 $x^a\times x^b = x^{ab}$。

所以我们就可以对 $f(n,k,p) = n^k \ \bmod \ p$ 进行分解:

$$ f(n,k,p) = \begin{cases} f(n,\frac12k,p)^2\ \bmod\ p & (k\ \bmod\ 2 = 0) \\ f(n,\frac12(k-1),p)^2\ \times n \ \bmod\ p &(k\ \bmod\ 2 = 1) \end{cases}$$

代码就不难写了:

int power(int base, int freq, int mod) {
    int ans = 1, tmp = base;
    while (freq > 0) {
        if (freq % 2 == 1) ans = ans * tmp % mod;
        freq /= 2;
        tmp = tmp * tmp % mod;
    }
    return ans;
}

时间复杂度:$O(\log k)$。适用于指数较大的情况。

坑点分析

long long

完整代码

#include <bits/stdc++.h>
#define int long long

using namespace std;

int power(int base, int freq, int mod) {
    int ans = 1, tmp = base;
    while (freq > 0) {
        if (freq % 2 == 1) ans = ans * tmp % mod;
        freq >>= 1;
        tmp = tmp * tmp % mod;
    }
    return ans;
}

const int p = 1e9 + 7;
int t, n, k;

signed main() {
    cin >> t;
    while (t--) {
        cin >> n >> k;
        cout << power(n, k, p) << endl;
    }
    return 0;
}

upd 2022.2.1: 修改了部分字母及公式错误。

posted @   TernaKagiri  阅读(4)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下
点击右上角即可分享
微信分享提示