A http://codeforces.com/contest/912/problem/A
简单推导不等式
注意一个小地方,就是不要ans + 负数
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <set>
#include <vector>
#include <map>
using namespace std;
int main(int argc, char *argv[]) {
// freopen("A.txt", "r", stdin);
long long A, B, x, y, z;
while (cin >> A >> B) {
// scanf ("%d%d%d", &x, &y, &z);
cin >> x >> y >> z;
long long ans = 0;
long long zero = 0;
ans += max(zero, 2 * x + y - A);
ans += max(zero, y + 3 * z - B);
// printf("%d\n", ans);
cout << ans << endl;
}
return 0;
}
B http://codeforces.com/contest/912/problem/B
被Hack一次...
题目是:n个数选k个,求k个数的最大异或的结果
注意只要K>=2 就可以取到最大的数,也就是如果n是m位,最大数就是二进制表示为m个1的数
另外K=1的时候,最大的数是n
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <set>
#include <vector>
#include <map>
using namespace std;
int main(int argc, char *argv[]) {
// freopen("B.txt", "r", stdin);
long long ans, n, k, tmpn;
while (cin >> n >> k) {
if (k == 1) {
cout << n << endl;
continue;
}
ans = 0;
tmpn = n;
int wei = 0;
while (tmpn) {
wei ++;
tmpn /= 2;
ans = ans * 2 + 1;
// if ((k == 1 && wei == 1) || k>=2 ) {
// ans += 1;
// }
}
cout << ans << endl;
}
return 0;
}
D http://codeforces.com/contest/912/problem/D
蛮好的一个题,当时大致明白该怎么做,但是就是推到不出来被r*r的square覆盖t次的小方格一共几个,然后看了下solution明白了,可以BFS搜索,因为中心的位置一定是被覆盖次数最多的,所以中心的四周的放进优先队列即可。
有一点需要解释的是下面的fourmin函数,因为下图,所以是四个值的min作为可能的列数
参考了这个:https://www.cnblogs.com/cxhscst2/p/8215674.html
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <set>
#include <vector>
#include <map>
#include <queue>
using namespace std;
struct Node {
int x,y;
double v;
Node(int x, int y, double v):x(x), y(y), v(v) {}
friend bool operator < (const Node &a, const Node &b) {
return a.v < b.v;
}
};
const int dx[] = {1, 0, -1, 0};
const int dy[] = {0, 1, 0, -1};
int fourmin(int a, int b, int c, int d) {
return min( min(a, b), min(c, d) );
}
double calv(int n, int m, int r, int x, int y) {
// int a = trimin(x+1, n-x, r);
// int b = trimin(y+1, m-y, r);
int a = fourmin(x+1, n-x, r, n - r + 1);
int b = fourmin(y+1, m-y, r, m - r + 1);
// cout << "n:" << n << " m:" << m << " r:" << r << " x:" << x << " y:" << y << " a:" << a << " b:" << b << " v:" << a/(1.0*r) * (1.0 *b/(1.0*r)) << endl ;
return a/(n - 1.0*r + 1.0) * (b/( m - 1.0*r + 1.0));
}
int main(int argc, char *argv[]) {
// freopen("D.txt", "r", stdin);
int n, m , r, k;
while (cin >> n >> m >> r >> k) {
priority_queue<Node> q;
double ans = 0.0;
int mid_x = n/2;
int mid_y = m / 2;
set< pair<int, int> > visit;
double mid_v = calv(n, m, r, mid_x, mid_y);
q.push(Node(mid_x, mid_y, mid_v));
visit.insert( make_pair(mid_x, mid_y) );
while (k-- && !q.empty()) {
Node tp = q.top();
q.pop();
ans += tp.v;
// cout << "==> k:" << k << " v:" << tp.v << '' << endl;
for (int i = 0; i < 4; i++) {
int xx = tp.x + dx[i];
int yy = tp.y + dy[i];
if (xx >= 0 && xx < n && yy >= 0 && yy < m && !visit.count(make_pair(xx, yy))) {
q.push( Node(xx, yy, calv(n, m, r, xx, yy)) );
visit.insert( make_pair(xx, yy) );
}
}
}
// cout << ans << endl;
printf("%.12lf\n", ans);
}
return 0;
}
E http://codeforces.com/contest/912/problem/E
题意:n个素数,给定k,求第k大的数,这个数满足,他的所有素数因子都在之前给的n个素数中
很值得练习的题。
做法:
先把n个数分成两份,假设第一份能组成a个数,第二份能组成b个数,那么如果不分的话,需要存储a*b个数,太大了,所以需要分一下,组成的意思是,比如2,3两个数,可以组成2,3,4,6,9....等
然后求出这a个数和b个数,排序
对于a中的一个数ta,所有在b中的数tb,只要满足 ta * tb <= INF, 那么ta*tb的所有因子就在n个数里面,于是就可以计数了。
二分答案,因为只要>答案的,都会有>k个数满足所有因子就在n个数里面,于是就可以计数了 满足二分性质
DFS和二分那里写法需要注意一下。
参考了 https://www.cnblogs.com/FxxL/p/8213922.html
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <set>
#include <vector>
#include <map>
using namespace std;
typedef long long ll;
const ll INF=1e18;
vector<ll> seg[2];
int n;
ll k;
vector<int>p;
void dfs(int pst, int pen, ll v, int seg_id) {
if (v > INF) return;
seg[seg_id].push_back(v);
for (int i = pst; i < pen; i++) {
if ( v <= INF / p[i] )
dfs(i, pen, v * p[i], seg_id); //
}
}
ll cnt(ll num) {
ll j=0;
ll ret = 0;
for (int i = seg[0].size()-1; i >= 0; i--) {
while(j < seg[1].size() && seg[1][j] <= num/seg[0][i])
j++;
ret += j;
}
return ret;
}
ll solve() {
ll l = 0, r = INF, mid;
while (l < r-1) {
mid = (l + r) / 2;
if (cnt(mid) >= k) {
r = mid;
} else {
l = mid;
}
// cout << "l:" << l << " r:" << r << " cnt:" << cnt(mid) << endl;
}
return r;
}
int main(int argc, char *argv[]) {
// freopen("E.txt", "r", stdin);
scanf("%d", &n);
int t;
for (int i = 0; i < n; i++) {
scanf("%d", &t);
p.push_back(t);
}
cin >> k;
// cout << "start dfs" << endl;
dfs(0, min(7, n), 1, 0);
// cout << "dfs1:" << seg[0].size() << endl;
dfs(min(7,n), n, 1, 1);
// cout << "dfs2:" << seg[1].size() << endl;
sort(seg[0].begin(), seg[0].end());
sort(seg[1].begin(), seg[1].end());
cout << solve() << endl;
return 0;
}