19级第一次友谊赛B、C、F题

B题:
题意:给一个长度小于\(100\)的二进制数,你可以删除任意位置上的\(0\)\(1\)或不删除,问操作后这个二进制数能不能整除\(64\)
题解:因为可以删除一些数,那么不难发现能整除\(64\)的二进制数规律是有一个\(1\)后面至少有\(6\)\(0\),所以就是看这个二进制数有没有一个\(1\),后面带着\(6\)\(0\)及以上。有就是\(yes\)

C题:
题意:一个向上三角形能在下一天变成\(3\)个向上的三角形,\(1\)个向下的三角形。
一个向下三角形能在下一天变成\(3\)个向下的三角形,\(1\)个向上的三角形。
\(0\)天有\(1\)个向上的三角形,问第\(n\)天有几个向上的三角形?
题解:假设\(a[i]\)\(b[i]\)分别表示第\(i\)天有的向上和向下的三角形个数,那么不难得到:
\(a[i]=3*a[i-1]+b[i-1]\)
\(b[i]=a[i-1]+3*b[i-1]\)
所以,\(a[i]-b[i]=2*(a[i-1]-b[i-1])\)
\(a[i]-b[i]\)看成一个函数,那么解得\(a[i]-b[i]=2^i\)
\(a[i]+b[i]=4^i\)
所以\(a[i]=2^{i-1}+2^{2i-1}\)
对上式求快速幂即可。

F题:
题意:计算有多少个二元组\(pair<i, j>\),满足在\(a[i]\)\(\leq\)\(y\)\(\leq\)\(a[j]\)这个范围内,正好有\(k\)个是\(x\)的倍数的数。
题解:对数组\(a\)进行排序,遍历每个元素\(a[i]\),先求出大于等于\(a[i]\)的第一个是\(x\)倍数的数\(p\),然后用\(p\)求出第\(k\)个是\(x\)倍数的数\(p_1\)和第\(k+1\)个是\(x\)倍数的数\(p_2\),然后对\(a\)数组二分出\(p_1\)\(p_2\)\(a\)数组第一次出现的位置\(l\)\(r\)\(r-l\)就是元素\(a[i]\)的贡献。对每个元素都进行上述操作计算答案即可。当\(k=0\)时注意\(p_1\)的取值。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;

const int N = 1e5 + 5;

int n, x, k;
LL res, ans, a[N];

int main() {
  scanf("%d %d %d", &n, &x, &k);
  for (int i = 1; i <= n; i++) scanf("%lld", a + i);
  sort(a + 1, a + 1 + n);
  for (int i = 1; i <= n; i++) {
    res = 1LL * (a[i] / x + (a[i] % x != 0)) * x;
    ans += lower_bound(a + 1, a + 1 + n, res + 1LL * k * x) - lower_bound(a + 1, a + 1 + n, max(a[i], res + 1LL * (k - 1) * x));
  }
  printf("%lld\n", ans);
  return 0;
}

猜你喜欢

转载自www.cnblogs.com/ChaseNo1/p/11869933.html