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: 修改了部分字母及公式错误。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下