2020.7.4 热身训练赛(四)

Table of Contents

  1. 2020.7.4 热身训练赛(四)
    1. A - Zeros and Ones
      1. solution
      2. code

2020.7.4 热身训练赛(四)

A - Zeros and Ones

solution

折半搜索。

  1. __builtin_popcount() 比我手打的函数要快,以后就用它了。
  2. 折半搜索计算答案的一半长度不能为零,要取(x+y)-(x+y)/2,要不然无法计算答案。
  3. lower_bound返回的是第一个大于等于这个数的地址,upper_bound返回第一个大于这个数的地址。
  4. 二维vector的写法,多组数据,用后要清零。

code

include <bits/stdc++.h>

using namespace std;
#define lbrg p[c].begin(), p[c].end() //lower_bound range
int x, y,mo, k;
vector<vector > p(50);
int main() {
freopen("zeros.in", "r", stdin);
int T;
scanf("%d", &T);
while (T--) {
scanf("%d%d%d%d", &x, &y, &mo, &k);

int rm = (x + y) >> 1; //二进制下右边的长度
int lm = x + y - rm; //左边的长度
for (int i = 0; i < (1 << rm); ++i) {
int c1 = __builtin_popcount(i);
p[c1].push_back(i % mo);
}
for (int i = 0; i < 50; ++i)
sort(p[i].begin(), p[i].end());
ll ans = 0;
for (ll i = 0; i < (1 << lm); ++i) {
if (((i >> (lm - 1)) & 1) == 0) continue;
int c1 = __builtin_popcount(i);
int c = x - c1;
if (c < 0) continue;
int lk = (i << rm) % mo;
if (lk <= k) {
ans += lower_bound(lbrg, mo - lk) - lower_bound(lbrg, k - lk);
} else {
ans += lower_bound(lbrg,mo - lk) - p[c].begin();
ans += lower_bound(lbrg, mo) - lower_bound(lbrg, mo + k - lk);

}
}
printf("%lld\n", ans);
for (int i = 0; i < 50; ++i)
p[i].clear();
}
return 0;
}

posted @ 2020-07-06 10:34  沐灵_hh  阅读(150)  评论(0)    收藏  举报