2020牛客暑期多校训练营(第七场)A、B、C、D、H、J题解及补题

2020牛客暑期多校训练营(第七场)题解及补题

比赛过程

这场打出了牛客排名新低,原因一来这场题目难度差别较大,我们前期思考的有点慢也wa了很多发罚时炸了,二来读题能力确实不太行,J题读了一小时多才读懂,已经没是没时间写了。

题解

A

题意

给一个半径为 r r r的圆,在圆内找到 n n n个整数点,求 ∑ i = 1 n − 1 ∑ j = i + 1 n d i s t ( i , j ) 2 \sum_{i=1}^{n-1}\sum_{j=i+1}^{n}dist(i,j)^2 i=1n1j=i+1ndist(i,j)2的最大值,其中 d i s t ( i , j ) dist(i,j) dist(i,j)指点 i i i与点 j j j之间的欧几里得距离。

解法

通过拆分计算 ∑ i = 1 n − 1 ∑ j = i + 1 n d i s t ( i , j ) 2 = n ∑ i = 1 n ( x i 2 + y i 2 ) − ( ∑ i = 1 n x i ) 2 − ( ∑ i = 1 n y i ) 2 \sum_{i=1}^{n-1}\sum_{j=i+1}^{n}dist(i,j)^2=n\sum_{i=1}^{n}(x_{i}^2+y_{i}^2)-(\sum_{i=1}^{n}x_{i})^2-(\sum_{i=1}^{n}y_{i})^2 i=1n1j=i+1ndist(i,j)2=ni=1n(xi2+yi2)(i=1nxi)2(i=1nyi)2,维护一个 d p [ i ] [ j ] [ k ] dp[i][j][k] dp[i][j][k]表示前 i i i个点横坐标和为 j j j,纵坐标和为 k k k每个点到圆心距离的平方和的最大值,根据 d p [ i ] [ j ] [ k ] dp[i][j][k] dp[i][j][k]更新 a n s [ i ] [ r ] ans[i][r] ans[i][r] a n s [ i ] [ r ] = m a x ( i ∗ d p [ i ] [ j ] [ k ] − j 2 − k 2 ) ans[i][r]=max(i\ast dp[i][j][k]-j^2-k^2) ans[i][r]=max(idp[i][j][k]j2k2)

代码
#pragma GCC optimize("O3")
#pragma G++ optimize("O3")

#include <bits/stdc++.h>
//#include <ext/pb_ds/assoc_container.hpp>
//#include <ext/pb_ds/tree_policy.hpp>
//#include <ext/pb_ds/priority_queue.hpp>

//using namespace __gnu_pbds;
using namespace std;

#define ll long long
#define ld long double
#define ull unsigned long long
#define mst(a, b) memset((a), (b), sizeof(a))
#define mp(a, b) make_pair(a, b)
#define pi acos(-1)
#define endl '\n'
#define pii pair<int, int>
#define pll pair<ll, ll>
#define pdd pair<double, double>
#define vi vector<int>
#define vl vector<ll>
#define pb push_back
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
#define lowbit(x) x &(-x)
#define all(x) (x).begin(), (x).end()
#define sf(x) scanf("%d", &x)
#define pf(x) printf("%d\n", x)
#define debug(x) cout << x << endl
#define mod(x) (x % mod + mod) % mod

template <typename T>
void read(T &x) {
   
   
    x = 0;
    char ch = getchar();
    ll f = 1;
    while (!isdigit(ch)) {
   
   
        if (ch == '-')
            f *= -1;
        ch = getchar();
    }
    while (isdigit(ch)) {
   
   
        x = x * 10 + ch - 48;
        ch = getchar();
    }
    x *= f;
}

const int INF = 0x3f3f3f3f;
const ll inf = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-8;
const int maxn = 3e3 + 7;
const int maxm = 1e5 + 7;
const int mod = 1e9 + 7;

#define IO ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
//template<typename T> using ordered_set = tree<T,null_type,less<T>,rb_tree_tag,tree_order_statistics_node_update>;
struct node {
   
   
    int r, x, y;
} q[maxn];
bool cmp(node a, node b) {
   
   
    return a.r < b.r;
}
int dp[10][606][606], ans[10][35], tot = 0;
void init() {
   
   
    for (int i = -30; i <= 30; ++i)
        for (int j = -30; j <= 30; ++j)
            if (i * i + j * j <= 900)
                q[++tot] = {
   
   i * i + j * j, i, j};
    sort(q + 1, q + 1 + tot, cmp);
    mst(dp, -INF);
    int cnt = 1;
    dp[0][300][300] = 0;
    for (int r = 1; r <= 30; ++r) {
   
   
        for (; cnt <= tot && q[cnt].r <= r * r; ++cnt) {
   
   
            node res = q[cnt];
            for (int i = 1; i <= 8; ++i)
                for (int j = -r * i + 300; j <= r * i + 300; ++j)
                    for (int k = -r * i + 300; k <= r * i + 300; ++k)
                        dp[i][j][k] = max(dp[i][j][k], dp[i - 1][j - res.x][k - res.y] + res.r);
        }
        for (int i = 1; i <= 8; ++i)
            for (int j = -r * i; j <= r * i; ++j)
                for (int k = -r * i; k <= r * i; ++k)
                    ans[i][r] = max(ans[i][r], i * max(dp[i][j + 300][k + 300], 0) - j * j - k * k);
    }
}
int main() {
   
   
    IO;
    init();
    int t;
    cin >> t
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值