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;
}
View Code

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);
}
View Code

 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;
}
View Code

 

posted @ 2018-04-02 08:58  Aragaki  阅读(247)  评论(0编辑  收藏  举报