​传送门​

Codeforces Global Round 17 D. Not Quite Lee(gcd)_算法

题意:

给你一个序列a,对于数Codeforces Global Round 17 D. Not Quite Lee(gcd)_整除_02,将其写成任意Codeforces Global Round 17 D. Not Quite Lee(gcd)_整除_02个连续的数,记第Codeforces Global Round 17 D. Not Quite Lee(gcd)_整除_02组数的和为Codeforces Global Round 17 D. Not Quite Lee(gcd)_算法_05,现要你找出所有的Codeforces Global Round 17 D. Not Quite Lee(gcd)_算法_05的组合,使每个组合中的sum的和为0。

思路:

经过推理,不难发现:
对于Codeforces Global Round 17 D. Not Quite Lee(gcd)_整除_02为偶数的情况,它的贡献为Codeforces Global Round 17 D. Not Quite Lee(gcd)_算法_08,k为任意整数,下同;
对于Codeforces Global Round 17 D. Not Quite Lee(gcd)_整除_02为奇数的情况,它的贡献为Codeforces Global Round 17 D. Not Quite Lee(gcd)_线性代数_10
同时,我们也可以得出第一个重要结论:当选取的Codeforces Global Round 17 D. Not Quite Lee(gcd)_线性代数_11全为奇数时,一定合法。
继续推理可得出下一个结论:**当选取的Codeforces Global Round 17 D. Not Quite Lee(gcd)_整除_02至少有一个奇数时,一定合法。*,证明如下
记我们选取的数的集合为Codeforces Global Round 17 D. Not Quite Lee(gcd)_线性代数_13,且其中存在x个奇数,要证明选取的数合法,
即证明:Codeforces Global Round 17 D. Not Quite Lee(gcd)_线性代数_14=Codeforces Global Round 17 D. Not Quite Lee(gcd)_整除_15这个式子成立
而等式右边的式子又可以等价于:gcd(Codeforces Global Round 17 D. Not Quite Lee(gcd)_线性代数_16)*k,这一步不多做阐述,
即要证明:Codeforces Global Round 17 D. Not Quite Lee(gcd)_线性代数_14=gcd(Codeforces Global Round 17 D. Not Quite Lee(gcd)_线性代数_16)*k,
记S = Codeforces Global Round 17 D. Not Quite Lee(gcd)_线性代数_19
即证明:gcd(Codeforces Global Round 17 D. Not Quite Lee(gcd)_线性代数_16) | S/2
易得:gcd(Codeforces Global Round 17 D. Not Quite Lee(gcd)_线性代数_16) | S且由于Codeforces Global Round 17 D. Not Quite Lee(gcd)_线性代数_22中存在奇数,因而gcd(Codeforces Global Round 17 D. Not Quite Lee(gcd)_线性代数_16) 一定不能整除2,所以gcd(Codeforces Global Round 17 D. Not Quite Lee(gcd)_线性代数_16) | S/2一定成立,
证毕。
接下来看全为偶数的情况,先说结论:我们将所有的偶数写为Codeforces Global Round 17 D. Not Quite Lee(gcd)_算法_25的形式,则选取的序列满足其中k值最小的数为偶数时,就合法。
证明如下
同样是上面的那个式子:gcd(Codeforces Global Round 17 D. Not Quite Lee(gcd)_线性代数_16) | S/2,现在b序列全为偶数,将其中每个数都写为Codeforces Global Round 17 D. Not Quite Lee(gcd)_c语言_27的形式,设最小的k为Codeforces Global Round 17 D. Not Quite Lee(gcd)_算法_28,把gcd(Codeforces Global Round 17 D. Not Quite Lee(gcd)_线性代数_16)也写为上述形式,则其等于Codeforces Global Round 17 D. Not Quite Lee(gcd)_线性代数_30,且x一定为奇数,不难得出x | S/2,现在只需要证明:Codeforces Global Round 17 D. Not Quite Lee(gcd)_c语言_31 | S/2,我们将S/2拆成序列的形式来看就是:{Codeforces Global Round 17 D. Not Quite Lee(gcd)_c语言_32},在这个除以2之后的序列中,原来刚好包含Codeforces Global Round 17 D. Not Quite Lee(gcd)_c语言_31的数都变为了包含Codeforces Global Round 17 D. Not Quite Lee(gcd)_c语言_34的数,而如果这些的个数为奇数,那么再让其除以Codeforces Global Round 17 D. Not Quite Lee(gcd)_c语言_31则会出现小数,而如果个数为偶数,那么就可以让每两个Codeforces Global Round 17 D. Not Quite Lee(gcd)_c语言_34合并为一个Codeforces Global Round 17 D. Not Quite Lee(gcd)_c语言_31,即:选取的序列满足其中k值最小的数为偶数时,就合法。
证毕。
最后的答案就用上面的结论即可得出。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll mod = 1e9+7;
ll qpow(ll a, ll b)
{
ll res = 1;
while(b)
{
if(b&1)res = res*a%mod;
b = b>>1;
a = a*a%mod;
}
return res;
}
int sum[40];
ll a[200010];
ll suf[40];
int main()
{
int n;
cin>>n;
ll even = 0,odd = 0;
for(int i = 1; i <= n; i++)
{
cin>>a[i];
if(a[i]%2)odd++;
else even++;
if(a[i]%2==0)
{
int k = 0;
ll now = a[i];
while(now%2==0)
{
now/=2;
k++;
}
sum[k]++;
}
}
for(int i = 31; i >= 1; i--)
{
suf[i] = suf[i+1]+sum[i];
}
ll ans = qpow(2,n)+mod-qpow(2,even);
ans%=mod;
for(int i = 1; i <= 31; i++)
{
if(sum[i])
{
ans += (qpow(2,sum[i]-1)-1)*qpow(2,suf[i+1]);
ans%=mod;
}
}
cout<<ans%mod<<endl;
}