Codeforces 1610D. Not Quite Lee

传送门

题目大意

思路

设选出的子序列中第 \(i\) 个数字为 \(b_i\) , 第起始的数字为 \(x_i\) ,于是若该子序列是好的,则 \(\sum_{i=1}^{n}\frac{(2x_i+b_i-1)b_i}{2}=0\) ,即 \(\sum_{i=1}^n b_ix_i=-\sum_{i=1}^n\frac{b_i(b_i-1)}{2}\) ,对于一个给定的子序列,等式右侧是一个定值,根据裴蜀定理,如果有解,那么有 \(gcd(b_1,...,b_n)|\sum_{i=1}^n\frac{b_i(b_i-1)}{2}\) ,即
\(2|\sum_{i=1}^n\frac{b_i(b_i-1)}{gcd(b_1,...,b_n)}\) ,设 \(gcd(b_1,...,b_n)=2^t,2\nmid k\)\(c_i=\frac{b_i}{2^t}\) , 于是
\(2|\sum_{i=1}^n\frac{c_i2^t(c_i2^t-1)}{2^tk}\to2|\sum_{i=1}^n\frac{c_i(c_i2^t-1)}{k}\to2|\sum_{i=1}^nc_i(c_i2^t-1)\) ,于是我们得到了一个子序列是好的需要满足的条件,接下来我们可以枚举 \(t\) 来计算,记 \(2^t|a\) 并且 \(2^{t+1}\nmid a\) 的数量为 \(cnt_t\) ,当 \(t=0\) 时,显然直接可以满足条件,此时的子序列数为 \((2^{cnt_0}-1)2^{m-cnt_0}\) ,对于其他的 \(t\) ,条件变为 \(2|\sum_{i=1}^nc_i\) ,必须要使得子序列中有偶数个可以正好被 \(2^t\) 整除的数字,并且至少有 \(1\) 个,于是此时好的子序列数量为 \((2^{cnt_t-1}-1)2^{m-\sum_{i=1}^tcnt_i}\) ,最后求和即为答案。

代码

#include<bits/stdc++.h>
#include<unordered_map>
#include<unordered_set>
using namespace std;
using LL = long long;
using ULL = unsigned long long;
using PII = pair<int, int>;
using TP = tuple<int, int, int>;
#define all(x) x.begin(),x.end()
//#define int LL
//#define lc p*2
//#define rc p*2+1
#define endl '\n'
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
//#pragma warning(disable : 4996)
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
const double eps = 1e-8;
const LL MOD = 1000000007;
const LL mod = 998244353;
const int maxn = 200010;

LL N, A[maxn], t[35];

LL calc(LL x)
{
	LL cnt2 = 0;
	while (x % 2 == 0)
	{
		cnt2++;
		x /= 2;
	}

	return cnt2;
}

LL qpow(LL a, LL x)
{
	LL ans = 1;
	while (x > 0)
	{
		if (x & 1)
			ans = ans * a % MOD;
		a = a * a % MOD;
		x >>= 1;
	}

	return ans;
}

void solve()
{
	LL ans = 0, tmp = t[0];
	ans = (ans + (qpow(2LL, t[0]) - 1 + MOD) % MOD * qpow(2LL, N - tmp) % MOD) % MOD;
	for (int i = 1; i <= 29; i++)
	{
		tmp += t[i];
		if (t[i] >= 2)
			ans = (ans + (qpow(2LL, t[i] - 1) - 1 + MOD) % MOD * qpow(2LL, N - tmp) % MOD) % MOD;
	}
	cout << ans << endl;
}

int main()
{
	IOS;
	cin >> N;
	for (int i = 1; i <= N; i++)
		cin >> A[i], t[calc(A[i])]++;
	solve();

	return 0;
}
posted @ 2022-04-17 16:41  Prgl  阅读(41)  评论(0)    收藏  举报