Codeforces 1610D. Not Quite Lee
思路
首先容易发现
如果 b i b_i bi 是奇数,那么它的贡献可以写成 k i b i k_ib_i kibi 其中 k i k_i ki 是任意整数
如果 b i b_i bi 是偶数,那么可以写成 b i 2 + k i b i \cfrac{b_i}{2}+k_ib_i 2bi+kibi
稍微推一下可以发现,一个序列里只要有一个奇数那么肯定有一种方法变为0
奇数和奇数相消取 l c m lcm lcm
奇数和偶数相消写成丢番图方程的形式,由裴蜀定理一定有解(两者的 gcd \gcd gcd 一定为奇数,所以右边的除2不用管)
那么只需要考虑只有偶数的情况
先说结论,将偶数写成 2 k ∗ c 2^k*c 2k∗c 的形式,那么将所有 k k k 相同的数看做整体,分别记数量为 t 1 , t 2 , . . . , t k t_1,t_2,...,t_k t1,t2,...,tk
那么答案就是
( 2 n − 2 ∑ t i ) + ∑ i = 1 k ( ( 2 t i − 1 − 1 ) ∗ 2 ∑ j = i + 1 k t j ) \left(2^n-2^{\sum t_i}\right) + \sum_{i=1}^{k}\left((2^{t_i-1}-1)*2^{\sum_{j=i+1}^{k}t_j}\right) (2n−2∑ti)+i=1∑k((2ti−1−1)∗2∑j=i+1ktj)
第一部分好理解,就是所有情况减去只有偶数的情况,而第二部分就是考虑只有偶数的情况里哪些是成立的
首先可以发现,选择的数里面2的次幂最小的数一定要出现偶数次,否则依旧写成一次不定方程的形式,用充要条件可判断无解(见 wiki )
证明:
不妨设选了
x
x
x 个数,那么就可以写成
∑
i
=
1
x
(
2
k
i
−
1
∗
c
i
)
=
∑
i
=
1
x
(
n
i
∗
2
k
i
∗
c
i
)
\sum_{i=1}^x\left( 2^{k_i-1}*c_i \right) = \sum_{i=1}^x\left( n_i*2^{k_i}*c_i \right)
i=1∑x(2ki−1∗ci)=i=1∑x(ni∗2ki∗ci)
这个等式有整数解的充要条件是
gcd ( 2 k 1 ∗ c 1 , 2 k 2 ∗ c 2 , . . . ) ∣ ∑ i = 1 x ( 2 k i − 1 ∗ c i ) \gcd\left( 2^{k_1}*c_1,2^{k_2}*c_2,... \right)\mid\sum_{i=1}^x\left( 2^{k_i-1}*c_i \right) gcd(2k1∗c1,2k2∗c2,...)∣i=1∑x(2ki−1∗ci)
因为 c i c_i ci 都是奇数,可以稍微改写一下
gcd ( 2 k 1 , 2 k 2 , . . . ) ∗ gcd ( c 1 , c 2 , . . . ) ∣ ∑ i = 1 x ( 2 k i − 1 ∗ c i ) \gcd\left( 2^{k_1},2^{k_2},... \right)*\gcd\left( c_1,c_2,... \right)\mid\sum_{i=1}^x\left( 2^{k_i-1}*c_i \right) gcd(2k1,2k2,...)∗gcd(c1,c2,...)∣i=1∑x(2ki−1∗ci)
不难发现成立的充要条件等价于
gcd ( 2 k 1 , 2 k 2 , . . . ) ∣ ∑ i = 1 x ( 2 k i − 1 ∗ c i ) \gcd\left( 2^{k_1},2^{k_2},... \right)\mid\sum_{i=1}^x\left( 2^{k_i-1}*c_i \right) gcd(2k1,2k2,...)∣i=1∑x(2ki−1∗ci)
即
min ( 2 k 1 , 2 k 2 , . . . ) ∣ ∑ i = 1 x ( 2 k i − 1 ∗ c i ) \min\left( 2^{k_1},2^{k_2},... \right)\mid\sum_{i=1}^x\left( 2^{k_i-1}*c_i \right) min(2k1,2k2,...)∣i=1∑x(2ki−1∗ci)
现在考虑转化右边,记 min ( k 1 , k 2 , . . . ) = Δ k \min(k_1,k_2,...)=\Delta k min(k1,k2,...)=Δk
那么右边可以写作
2 Δ k − 1 ∗ ∑ ( 2 k i − Δ k ∗ c i ) 2^{\Delta k-1}*\sum\left(2^{k_i-\Delta k}*c_i \right) 2Δk−1∗∑(2ki−Δk∗ci)
所以充要条件等价于满足和式是2的倍数,显然,这也等价于 k i = Δ k k_i=\Delta k ki=Δk 的项有偶数个,也就是上面的结论
反之,易得如果最小的2的次幂有偶数个,那么无论拥有更大2的次幂的数怎么选都一定有解
所以枚举选的最小的2的次幂,用在其中选偶数个的方案数乘上在更大2的次幂中随便选的方案数在再累加就是仅有偶数的情况,即
∑ i = 1 k ( ( 2 t i − 1 − 1 ) ∗ 2 ∑ j = i + 1 k t j ) \sum_{i=1}^{k}\left((2^{t_i-1}-1)*2^{\sum_{j=i+1}^{k}t_j}\right) i=1∑k((2ti−1−1)∗2∑j=i+1ktj)
前一项由二项式定理易得(要去除什么都不选的情况,因为枚举到这里的时候要选)
说的很长实际代码很短(
其实推出来之后容易发现,奇数也可直接扔进去做(
代码
#include <bits/stdc++.h>
using namespace std;
std::mt19937 rng(std::random_device{}());
typedef long double ld;
typedef long long ll;
typedef unsigned long long ull;
typedef const int& cint;
typedef const ll& cll;
typedef pair<int, int> pii;
typedef pair<int, ll> pil;
#define ls (loc<<1)
#define rs ((loc<<1)|1)
const int mod1 = 1e9+7;
const int mod2 = 998244353;
const int inf_int = 0x7fffffff;
const int hf_int = 0x3f3f3f3f;
const ll inf_ll = 0x7fffffffffffffff;
const double ept = 1e-9;
int n;
int a[200200];
int val[200];
ll to[200200];
void init() {
to[0] = 1;
for(int i=1; i<=200000; i++)
to[i] = to[i-1] * 2 % mod1;
}
int main() {
// freopen("1.in", "r", stdin);
//cout.flags(ios::fixed); cout.precision(8);
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
int T_=1;
// std::cin >> T_;
init();
for(int _T=1; _T<=T_; _T++) {
cin >> n;
ll sum = 0;
for(int i=1; i<=n; i++) cin >> a[i];
for(int i=1; i<=n; i++) {
if(a[i]&1) ++ sum;
else {
int r = 0;
while(!(a[i]%(1<<r))) ++r;
++val[r-1];
}
}
ll ans = (to[n] - to[n-sum] + mod1) % mod1;
int r = 0;
for(int i=1; i<=33; i++) {
if(!val[i]) continue;
r += val[i];
ans += (to[val[i]-1]-1) * to[n-sum-r];
ans %= mod1;
}
cout << ans << endl;
}
return 0;
}
题外话
其实C题把人心态搞炸以后就来做这题了,然后卡在了只有偶数的情况上,猜了个错的结论还过了样例(
实际上差不多已经推完了,要不是C(
幸亏拿的小号,要不铁定飞了,毕竟表现分只有1500多(
一段时间没训练竟然变得这么菜(
只希望接下来上海能发挥好,不要演队友(