SP32192 SUMMATION - SUMMATION
题目大意
给定有 $n$ 个数的数列 $s$,求这个数列的所有子序列之和的总和。答案对 $100000007$ 取模。
题意分析
观察样例表格。
易得,包括空序列在内,总的子序列数为 $8$,即 $2^3$。
也就是,对于有 $n$ 个数的数列,总的子序列数为 $2^n$。
对于一个数列中的元素 $s_i$,在所有数列中都有 $\frac12$ 存在 $s_i$,另一半不存在。也就是说,仅计算这个元素在所有序列中的和,为
$$s_i\times \frac12 \times 2^n = s_i \times 2^{n-1}$$
题目中所求的就是所有元素套上述式子的总和,即
$$ans = \sum_{i=1}^{n}s_i \times 2^{n-1} = 2^{n-1}\sum_{i=1}^{n}s_i$$
那么只要在输入的时候累加求和,再用快速幂算出 $2^{n - 1}$ 并相乘取模即可。
主要芝士
快速幂。
我们知道,乘方运算有结合律,即 $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) {
if (freq & 1) ans = ans * tmp % mod;
freq >>= 1;
tmp = tmp * tmp % mod;
}
return ans;
}
时间复杂度仅 $O(\log n)$。比起循环乘的 $O(n)$ 快了不少。
题目坑点
模数居然不是 $10^9+7$,而是 $10^8+7$,差评。
另:开 long long
。
完整代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
int t, n, ai, sum, res;
const int mod = 1e8 + 7;
int power(int base, int freq, int mod) {
int ans = 1, tmp = base;
while (freq) {
if (freq & 1) ans = ans * tmp % mod;
freq >>= 1;
tmp = tmp * tmp % mod;
}
return ans;
}
signed main() {
cin >> t;
for (int cs = 1; cs <= t; cs++) {
sum = 0;
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> ai;
sum = (sum + ai) % mod;
}
res = sum * power(2, n - 1, mod) % mod;
cout << "Case " << cs << ": " << res << endl;
}
return 0;
}
(不要脸地求个赞)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?