Codeforces 912 质因数折半 方格数学期望
A
B
#include <bits/stdc++.h> #define PI acos(-1.0) #define mem(a,b) memset((a),b,sizeof(a)) #define TS printf("!!!\n") #define pb push_back #define inf 1e9 //std::ios::sync_with_stdio(false); using namespace std; //priority_queue<int,vector<int>,greater<int>> que; get min const double eps = 1.0e-10; const double EPS = 1.0e-4; typedef pair<int, int> pairint; typedef long long ll; typedef unsigned long long ull; //const int maxn = 3e5 + 10; const int turn[4][2] = {{1, 0}, { -1, 0}, {0, 1}, {0, -1}}; //priority_queue<int, vector<int>, less<int>> que; //next_permutation ll Mod = 1000000007; set<int> need; map<int, bool> mp[200005]; vector<int> ans; int main() { ll n, k; cin >> n >> k; ll cnt = 0; for (ll i = 61; i >= 0; i--) { if ((1LL << i)&n) { cnt = i; break; } } if (k == 1) { cout << n << endl; } else { cout << (1LL << (cnt + 1)) - 1 << endl; } return 0; }
D
每个点(i,j)在min(i,min(r,n-r+1))*min(j,min(r,m-r+1))个正方形内
这个点的贡献为number*在多少个正方形内/(n-r+1)/(m-r+1)
#include <bits/stdc++.h> #define PI acos(-1.0) #define mem(a,b) memset((a),b,sizeof(a)) #define TS printf("!!!\n") #define pb push_back #define inf 1e9 //std::ios::sync_with_stdio(false); using namespace std; //priority_queue<int,vector<int>,greater<int>> que; get min const double eps = 1.0e-10; const double EPS = 1.0e-4; typedef pair<int, int> pairint; typedef long long ll; typedef unsigned long long ull; //const int maxn = 3e5 + 10; const int turn[4][2] = {{1, 0}, { -1, 0}, {0, 1}, {0, -1}}; //priority_queue<int, vector<int>, less<int>> que; //next_permutation ll Mod = 1000000007; ll area; ll chang, kuang; ll n, m, r, k; double anser = 0; map<ll, bool> mp[100005]; struct node { ll x, y, sum; friend operator<(node a, node b) { return a.sum < b.sum; } }; priority_queue<node> que; ll judge(int x, int y) { if (x == (n + 1) / 2 && (n & 1) && y == (m + 1) / 2 && (m & 1)) { return 1; } if ((x == (n + 1) / 2 && (n & 1)) || (y == (m + 1) / 2 && (m & 1))) { return 2; } return 4; } int main() { cin >> n >> m >> r >> k; chang = min(r, n - r + 1), kuang = min(r, m - r + 1); area = (n - r + 1) * (m - r + 1); node cnt; cnt.x = (n + 1) / 2, cnt.y = (m + 1) / 2, cnt.sum = min(cnt.x, chang) * min(cnt.y, kuang); que.push(cnt); while (!que.empty() && k) { node cur = que.top(); que.pop(); ll number = judge(cur.x, cur.y); number = min(number, k); k -= number; anser += 1.0 * number * cur.sum / area; node todo; todo.x = cur.x - 1, todo.y = cur.y, todo.sum = min(todo.x, chang) * min(todo.y, kuang); if (todo.x >= 1 && todo.y >= 1 && mp[todo.x][todo.y] == 0) { que.push(todo); mp[todo.x][todo.y]++; } todo.x = cur.x, todo.y = cur.y - 1, todo.sum = min(todo.x, chang) * min(todo.y, kuang); if (todo.x >= 1 && todo.y >= 1 && mp[todo.x][todo.y] == 0) { que.push(todo); mp[todo.x][todo.y]++; } } printf("%.10f\n", anser); }
E
给你一个大小为N(N<=16)的集合
然后再给你个N个质数 要求你求第K小的一个满足要求的数 一个数满足要求当且仅当其质因数都在集合内
二分搜索 分成两个集合各自乘积 然后从一个集合的number[0].size()开始 递减 从另外一个 number[1].size()开始递增 用一个cur来维护每个number[0][i]的贡献
因为当最坏的情况时后面的数比前面的大 所以折半的时候前面的集合要适当小一点不然会T
#include <bits/stdc++.h> #define PI acos(-1.0) #define mem(a,b) memset((a),b,sizeof(a)) #define TS printf("!!!\n") #define pb push_back #define inf 1e9 //std::ios::sync_with_stdio(false); using namespace std; //priority_queue<int,vector<int>,greater<int>> que; get min const double eps = 1.0e-10; const double EPS = 1.0e-4; typedef pair<int, int> pairint; typedef long long ll; typedef unsigned long long ull; //const int maxn = 3e5 + 10; const int turn[4][2] = {{1, 0}, { -1, 0}, {0, 1}, {0, -1}}; //priority_queue<int, vector<int>, less<int>> que; //next_permutation ll Mod = 1000000007; ll k; ll limit = 1e18; ll num[30]; double anser = 0; vector<ll> number[2]; void dfs(int l, int r, ll x, int pos) { number[pos].push_back(x); for (int i = l; i <= r; i++) { if (limit / num[i] >= x) { dfs(i, r, x * num[i], pos); } } } ll check(ll x) { ll sum = 0; ll cur = 0; for (int i = number[0].size() - 1; i >= 0; i--) { while (cur < number[1].size() && number[1][cur] <= x / number[0][i]) { ++cur; } sum += cur; } return sum; } int main() { int n; cin >> n; for (int i = 1; i <= n; i++) { cin >> num[i]; } sort(num + 1, num + 1 + n); cin >> k; //TS; dfs(1, min(6, n), 1, 0); dfs(min(6, n) + 1, n, 1, 1); cout << number[0].size() << " " << number[1].size() << endl; //TS; sort(number[0].begin(), number[0].end()); sort(number[1].begin(), number[1].end()); ll l = 0; ll r = 1e18; while (l < r - 1) { ll mid = (l + r) >> 1; if (check(mid) >= k) { r = mid; } else { l = mid; } } cout << r << endl; }