CF 456 div2 A,B,D,E 题解
2018-01-06 18:59
405 查看
传送门
A题: 水题直接做(注意爆int就是了)
B题: 注意看清楚题目是选不超过k个, 所以就很简单啦. 直接分情况讨论, k == 1时就输出n, k >= 2时就输出n的二进制位数全为1的那个数. (注意不要使用log2来计算, 会被卡精度! 比如二进制为58个1的那个数log2出来就等于58!)
AC Code
C懂题意也做不来.
D: 就是给你个n*m的格子, 可以在里面放养k条鱼, 每条鱼必须在不同的格子中, 随机撒网问扑到鱼的期望值是多少. 首先我们可以很简单的想到ans = 每次撒网区域中鱼的个数之和 / 总的撒网次数. 总的撒网次数好求就是(n-r+1)*(m-r+1). 那每次撒网区域中鱼的个数了, 如果暴力求就是n*m肯定不行. 所以我们转换思维求每条鱼可以被多少次撒网捉到, 也就是我们需要在n*m的格子中选取k个期望被捉到很多次的格子中, 然后向四周扩展要期望值最好的k个, 所以我们就可以从一定会被捉很多次的中间的那个位置其(n/2+1, m/2+1), 这个位置一定会被捉很多次, 然后向四周扩展, 用BFS, 然后就是对一个格子(x, y) 被网捉到的次数的计算 就是
times = (min(m+1, x+r) - max(x, r)) * (min(n+1, y+r) - max(y, r)); //可以画出来看看.
那么就可以写了, 注意用优先队列, 因为我们首先要期望值最高的出来.
AC Code
E: 题意就是给你n个不超过100的素数, 在不超过1e18的数中的素因子都在这n个中求第k大个数多少.
那么我们就要几个问题处理, 一是知道有哪些数了, 如何求第k大, 这个用二分很好求. 第二个就是如何求得这些数, 设D(N) 表示一个数集合, 其中所有的数的素数因子都在N中(因为D(N)中的数都可以用N中的数得到). 如果单独用一个数组存, D(N)个数可能多达8e8之多, 那么我们可以把这n个素数分成两堆A, B. 分别求出, 然后就可以用双指针的方法在O(D(A) + D(B)) 的时间中求出我们的数有多少小于等于它的. 具体实现请看代码. 还有就是如何分为两个集合了? 如果单纯前一半在A, 剩下的在B的话, D(A)也可能多达7e6,这也不行, 所以我们需要隔一个放在不同的A,B集合中, 这样D(A)最多1e6, 就符合我们的要求了. 如何求D(A)了, 我用的深搜.
具体请看代码
AC Code
A题: 水题直接做(注意爆int就是了)
B题: 注意看清楚题目是选不超过k个, 所以就很简单啦. 直接分情况讨论, k == 1时就输出n, k >= 2时就输出n的二进制位数全为1的那个数. (注意不要使用log2来计算, 会被卡精度! 比如二进制为58个1的那个数log2出来就等于58!)
AC Code
void solve() { ll n,k; while(cin >> n >> k ) { if (k == 1) { cout << n << endl; } else { ll ans = 1 ; while(ans <= n) ans <<= 1; cout << --ans << endl; } } }
C懂题意也做不来.
D: 就是给你个n*m的格子, 可以在里面放养k条鱼, 每条鱼必须在不同的格子中, 随机撒网问扑到鱼的期望值是多少. 首先我们可以很简单的想到ans = 每次撒网区域中鱼的个数之和 / 总的撒网次数. 总的撒网次数好求就是(n-r+1)*(m-r+1). 那每次撒网区域中鱼的个数了, 如果暴力求就是n*m肯定不行. 所以我们转换思维求每条鱼可以被多少次撒网捉到, 也就是我们需要在n*m的格子中选取k个期望被捉到很多次的格子中, 然后向四周扩展要期望值最好的k个, 所以我们就可以从一定会被捉很多次的中间的那个位置其(n/2+1, m/2+1), 这个位置一定会被捉很多次, 然后向四周扩展, 用BFS, 然后就是对一个格子(x, y) 被网捉到的次数的计算 就是
times = (min(m+1, x+r) - max(x, r)) * (min(n+1, y+r) - max(y, r)); //可以画出来看看.
那么就可以写了, 注意用优先队列, 因为我们首先要期望值最高的出来.
AC Code
int dx[] = {0, 0, 1, -1}; int dy[] = {1, -1, 0, 0}; ll n, m, r, k; ll cal(ll x, ll y) { return (min(m+1, x+r) - max(x, r)) * (min(n+1, y+r) - max(y, r)); // 横着 * 竖着 } struct node { int x, y; bool operator < (const node & a) const { return cal(x, y) < cal(a.x, a.y); } }; void solve() { while(cin >> n >> m) { cin >> r >> k ; int sx = m/2 + 1; int sy = n/2 + 1 ; priority_queue<node>q; map<pii, bool>mp; q.push(node{sx, sy}); mp[make_pair(sx, sy)] = 1; db ans = 0; for (int i = 1 ; i <= k ; i++) { node k = q.top(); q.pop(); ans += 1.0*cal(k.x, k.y); for (int j = 0 ; j < 4 ; j++) { int xx = k.x + dx[j], yy = k.y + dy[j]; if (mp[make_pair(xx, yy)]) continue; if (xx < 1 || xx > m || yy < 1 || yy > n) continue; mp[make_pair(xx, yy)] = 1; q.push(node{xx, yy}); } } ans /= 1.0*(n-r+1)*(m-r+1); printf("%.10f\n",ans); } }
E: 题意就是给你n个不超过100的素数, 在不超过1e18的数中的素因子都在这n个中求第k大个数多少.
那么我们就要几个问题处理, 一是知道有哪些数了, 如何求第k大, 这个用二分很好求. 第二个就是如何求得这些数, 设D(N) 表示一个数集合, 其中所有的数的素数因子都在N中(因为D(N)中的数都可以用N中的数得到). 如果单独用一个数组存, D(N)个数可能多达8e8之多, 那么我们可以把这n个素数分成两堆A, B. 分别求出, 然后就可以用双指针的方法在O(D(A) + D(B)) 的时间中求出我们的数有多少小于等于它的. 具体实现请看代码. 还有就是如何分为两个集合了? 如果单纯前一半在A, 剩下的在B的话, D(A)也可能多达7e6,这也不行, 所以我们需要隔一个放在不同的A,B集合中, 这样D(A)最多1e6, 就符合我们的要求了. 如何求D(A)了, 我用的深搜.
具体请看代码
AC Code
void dfs(vector<ll>&a, vector<ll>&b, ll cur = 1, int pos = 0, ll bound = INF) { if (pos >= a.size()) { //DFS求D(N). b.pb(cur); return ; } while (bound) { dfs(a, b, cur, pos + 1, bound); cur *= a[pos]; bound /= a[pos]; } } vector<ll>x, y; int cal(ll t) { int j = 0; ll ans = 0; for (int i = 0 ; i < x.size() ; i++) { while(j < y.size() && y[j] <= t / x[i]) j++; ans += j; //因为x是从大到小排序的. } return ans; } void solve() { int n; while(cin >> n) { vector<ll> a[2]; for (int i = 1 ; i <= n ; i++) { ll u ; cin >> u; a[i % 2 ].pb(u); } int k ; cin >> k ; x.clear(); y.clear(); dfs(a[0], x); dfs(a[1], y); sort(x.rbegin(), x.rend()); //从大到小排序. 这样就可以使用双指针的方法求k大. sort(y.begin(), y.end()); ll l = 1, r = INF, mid; ll ans = 1; while(r >= l) { mid = (l+r) >> 1; if (cal(mid) < k) { l = mid + 1; ans = l; } else r = mid - 1; } cout << ans << endl; } }
相关文章推荐
- Borya and Hanabi - CF#253 (Div. 2)C (442A) 状压暴力枚举
- CF 159 div2 d
- CF#FF (Div. 2) B.
- CF Round #240 (Div. 2) D
- cf_369_div 2_E
- CF #192(div2)
- 7/22 CF#173(div2)
- cf 194 div2 BEight Point Sets
- E. Soldier and Traveling (CF 304 div2) 最大流
- CF_DIV2_153
- 387 div2 cf 4
- CF&&CC百套计划3 Codeforces Round #204 (Div. 1) E. Jeff and Permutation
- CF--#334-div2--B
- Codeforces Round #397 (Div. 1 + Div. 2 combined) 题解(CF765A,CF765B,CF765C,CF765D,CF765E,CF765F)
- CF 257 DIV 2 D. Jzzhu and Cities (学会了使用优先队列优化的Dij 和 静态链表存储)
- [CF]codeforces round 369(div2)
- 13年7月13日CF练习 Codeforces Round #147 (Div. 2)
- CF RCC 2014 Warmup (Div. 2) D. Cunning Gena
- CF 294 div2 D. A and B and Interesting Substrings (hash)
- CF 92 div2 B