读完题目后,发现如果暴力枚举每种方案,时间复杂度非常高,似乎不是很可行。
注意到要求的是美丽值总和,也就是并不关心具体的方案,所以可以考虑分别求出每颗珠子的贡献。又因为同种颜色珠子的个数对贡献有影响,因此不妨对每种颜色的珠子分别计算,再累加即可。以上为大致思路。
具体地,对于第 \(i\) 种颜色,暴力枚举珠子数并计算对应的组合数,再计算出单次贡献和剩余的珠子选取的方案数(每颗都可选可不选),将它们乘起来,得到如下式子,式子的值即为第 \(i\) 种颜色的贡献(\(a_i\) 和 \(v_i\) 的含义如题):
\[\sum_{j=1}^{a_i}2^{n-a_i} \times C_{a_i}^{j} \times v_i^{j} \]总答案式子也不难得到:
\[\sum_{i=1}^n\sum_{j=1}^{a_i}2^{n-a_i} \times C_{a_i}^{j} \times v_i^{j} \]直接暴力计算,时间复杂度 \(O(n^2)\),可以获得 \(40\) 分。这里就不给出代码了。
考虑如何优化上述计算过程。发现 \(2^{n-a_i}\) 这一项对于每一个固定的 \(i\) 是不变的,因此可以在最后再乘上。对于剩下的部分,我们发现它与二项式的展开式非常相似,因此可以尝试配成二项式。
注意到 \(1\) 的任意正整数次方都为 \(1\),因此原式可以等价为
\[\sum_{j=1}^{a_i} C_{a_i}^{j} \times v_i^{j} \times 1^{a_i-j} \]这样就能化成 \((v_i + 1)^{a_i}\)。当然,该式子多算上了 \(j=0\) 的情况,此时的值为 \(1\),所以要在上述式子的基础上减 \(1\) 才是正确的。
总结上面的推导,可以得到以下计算总答案的式子:
\[\sum_{i=1}^n 2^{n - a_i} \times [(v_i+1)^{a_i}-1] \]使用快速幂计算即可,时间复杂度 \(O(n \log n)\)。
完整代码如下:
#include <iostream>
#include <cstdio>
#define int long long
#define MOD 1000000007
using namespace std;
int n,a[1000001],b[1000001],ans,sum = 1;
int qp( int a , int b )
{
int c = 1;
while( b )
{
if( b & 1 ) c = c * a % MOD;
b >>= 1;
a = a * a % MOD;
}
return c;
}
signed main()
{
cin >> n;
for( int i = 1 ; i <= n ; i ++ )
cin >> a[i],sum = sum * qp( 2 , a[i] ) % MOD;
for( int i = 1 ; i <= n ; i ++ )
{
cin >> b[i];
sum = sum * qp( qp( 2 , a[i] ) , MOD - 2 ) % MOD;
ans = ( ans + sum * ( qp( b[i] + 1 , a[i] ) - 1 + MOD ) % MOD ) % MOD;
sum = sum * qp( 2 , a[i] ) % MOD;
}
cout << ans;
return 0;
}
标签:qp,int,sum,LG10185,times,式子,MOD
From: https://www.cnblogs.com/-lilong-/p/18086121