2020 CCPC Henan
A. 班委竞选
签到题
#include <bits/stdc++.h>
using namespace std;
int32_t main() {
int n , m ;
cin >> n >> m;
vector<int> a( m+1 , 0 ) , b( m+1 , 0 );
for( int i = 1 , c , t ; i <= n ; i ++ ){
cin >> c >> t;
if( t > a[c] ) a[c] = t , b[c] = i;
}
for( int i = 1 ; i <= m ; i ++ )
cout << b[i] << " ";
return 0;
}
C. 我得重新集结部队
\(n\le 2\times 10^2\),所以直接\(O(n^2)\)的遍历就好了,如果是异虫直接加入队列,如果是狂热者先找出离他最近的传送过去,然后在暴力处理攻击范围内的虫即可
#include <bits/stdc++.h>
using namespace std;
#define int long long
int read() {
int x = 0, f = 1, ch = getchar();
while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
if (ch == '-') f = -1, ch = getchar();
while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x * f;
}
int32_t main() {
int n = read();
vector<int> res;
vector<tuple<int, int, int> > g;
for (int opt, x, y, a, b; n; n--) {
opt = read(), x = read(), y = read(), a = read();
if (opt == 1) g.emplace_back(x, y, a), res.push_back(g.size() - 1);
else {
a *= 3ll, b = read(), b = b * b;
int d = LLONG_MAX, dx, dy, t;
for (auto [r, c, h]: g) {
if (h <= 0) continue;
t = (r - x) * (r - x) + (c - y) * (c - y);
if (t < d) d = t, dx = r, dy = c;
}
x = dx, y = dy, t = -1;
for (auto &[r, c, h]: g) {
if (h <= 0) continue;
d = (r - x) * (r - x) + (c - y) * (c - y);
if( d <= b ){
h -= a;
if( h > 0ll ) t = -2;
}
}
res.push_back(t);
}
}
for( auto i : res )
if( i < 0 ){
if( i == -1 ) cout << "Yes\n";
else cout << "No\n";
}else{
if( get<2>(g[i]) > 0 ) cout << "Yes\n";
else cout << "No\n";
}
return 0;
}
E. 发通知
树状数组也是可以维护异或和的。先把\(a,b+1\)全部离散化,然后用一个数组维护每个时刻能够通知的数量,再用一个树状数组维护每个时刻的异或和即可。复杂度\(O(n\log n)\)
#include <bits/stdc++.h>
using namespace std;
class bit {
private:
int n;
vector<int> b;
int lowbit(int x) {
return (x & -x);
}
public:
bit(int n) : n(n) {
b = vector<int>(n + 1);
}
void add(int x, int val) {
for (int i = x; i <= n; i += lowbit(i))
b[i] += val;
return;
}
int getV(int x) {
int res = 0;
for (int i = x; i; i -= lowbit(i))
res += b[i];
return res;
}
};
class bit2 {
private:
int n;
vector<int> b;
int lowbit(int x) {
return (x & -x);
}
public:
bit2(int n) : n(n) {
b = vector<int>(n + 1);
}
void add(int x, int val) {
for (int i = x; i <= n; i += lowbit(i))
b[i] ^= val;
return;
}
int getV(int x) {
int res = 0;
for (int i = x; i; i -= lowbit(i))
res ^= b[i];
return res;
}
};
int read() {
int x = 0, f = 1, ch = getchar();
while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
if (ch == '-') f = -1, ch = getchar();
while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x * f;
}
int main() {
int n = read(), k = read();
vector<tuple<int, int, int> > a(n);
vector<int> b;
for (auto &[l, r, w]: a) l = read(), r = read()+1, w = read(), b.push_back(l), b.push_back(r);
sort(b.begin(), b.end());
auto t = unique(b.begin(), b.end())++;
int m = t - b.begin() + 5;
bit p(m);
bit2 q(m);
for (auto &[l, r, w]: a) {
l = lower_bound(b.begin(), t, l) - b.begin() + 1;
r = lower_bound(b.begin(), t, r) - b.begin() + 1;
p.add(l, 1), p.add(r, -1);
q.add(l, w), q.add(r, w);
}
int res = -1;
for( int i = 1 ; i < m ; i ++ ){
if( p.getV(i) < k ) continue;
res = max( res , q.getV(i) );
}
cout << res;
return 0;
}
I. 太阳轰炸
一道不太难的数学题
首先命中的概率是\(p=\min( 1 , (\frac{R_1+r}{R_2})^2)\),然后要击毁至少要命中$k=\left \lceil \frac{h}{a} \right \rceil $,根据二项式定理可知答案是
\[\sum_{i=k}^{k} C_n^i p^i(1-p)^{n-i}
\]
注意取模就好了
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int mod = 1e9 + 7;
int power(int x, int y) {
x = x % mod;
int ans = 1;
while (y) {
if (y & 1) ans = ans * x % mod;
y >>= 1, x = x * x % mod;
}
return ans;
}
int inv(int x) {
return power(x, mod - 2);
}
vector<int> fact, invFact;
void init(int n) {
fact = vector<int>(n + 1), invFact = vector<int>(n + 1);
fact[0] = 1, invFact[0] = inv(1);
for (int i = 1; i <= n; i++)
fact[i] = fact[i - 1] * i % mod, invFact[i] = inv(fact[i]);
return;
}
int C(int x, int y) {
return fact[x] * invFact[x - y] % mod * invFact[y] % mod;
}
int32_t main() {
int n, r1, r2, r, a, h;
cin >> n >> r1 >> r2 >> r >> a >> h;
init(n);
if (r1 + r >= r2) return cout << 1, 0;
int p, q;
p = (r1 + r) * inv(r2) % mod, p = p * p % mod, q = ((1 - p) % mod + mod) % mod;
int invQ = inv(q);
int res = 0;
for (int i = (h + a - 1) / a , s = power( p , i ) , t = power( q , n - i ) ; i <= n; i++)
res = (res + C(n, i) * s % mod * t % mod ) % mod , s = s * p % mod , t = t * invQ % mod;
cout << res;
return 0;
}