[luoguP10217/联合省选 2024] 季风

题意

给定 \(n,k,x,y\)\(2n\) 个整数 \(x_0,y_0,x_1,y_1,\dots,x_{n-1},y_{n-1}\)

找到最小的非负整数 \(m\),使得存在 \(2m\) 个实数 \(x_0',y_0',x_1',y_1',\dots,x_{m-1}',y_{m-1}'\) 满足以下条件,或报告不存在这样的 \(m\)

  • \(\sum \limits_{i=0}^{m-1} (x_i'+x_{i \bmod n})=x\)
  • \(\sum \limits_{i=0}^{m-1} (y_i'+y_{i \bmod n})=y\)
  • \(\forall 0\leq i\leq m-1,|x_i'|+|y_i'|\leq k\)

特别地,\(m=0\) 时,认为 \(\sum \limits_{i=0}^{m-1} (x_i'+x_{i \bmod n})\)\(\sum \limits_{i=0}^{m-1} (y_i'+y_{i \bmod n})\) 均为 \(0\)

sol

第三条限制等价于 \(|\sum \limits_{i=0}^{m-1}x_{i \bmod n}|+|\sum \limits_{i=0}^{m-1}y_{i \bmod n}| \le mk\),也就是 \(|x - \sum \limits_{i=0}^{m-1}x_i'|+|y - \sum \limits_{i=0}^{m-1}y_i'| \le mk\)
注意到可以拆分为不同周期:设 \(m=pn+q\),变为 \(|x - p\sum \limits_{i=0}^{n-1}x_i - \sum \limits_{i=0}^{q-1}x_i|+|y - p\sum \limits_{i=0}^{n-1}y_i - \sum \limits_{i=0}^{q-1}y_i| \le mk\),可以枚举每一个 \(q\),解这个绝对值不等式,求出最小的 \(p\) 的正整数解,取最小的 \(pn+q\) 即为答案。

代码

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>

using namespace std;
typedef long long LL;

const int N = 100005;
const LL INF = 9e18;
const double eps = 1e-8;

LL sx[N], sy[N];
int n, k, X, Y;
int T;
double l, r;
int dx[] = {1, 1, -1, -1}, dy[] = {1, -1, 1, -1};

void calc_range(double x, double y){
    l = max(l, x), r = min(r, y);
}

int main(){
    scanf("%d", &T);
    for (int cs = 1; cs <= T; cs ++ ) {
        scanf("%d%d%d%d", &n, &k, &X, &Y);
        for (int i = 1; i <= n; i ++ ) {
            scanf("%lld%lld", &sx[i], &sy[i]);
            sx[i] += sx[i - 1], sy[i] += sy[i - 1];
        }
        
        LL ans = 9e18;
        for (int i = 0; i < n; i ++ ) {
            l = -INF, r = INF;
            for (int j = 0; j < 4; j ++ ){
                LL coeff = dx[j] * sx[n] + dy[j] * sy[n] + (LL) n * k;
                LL lft = dx[j] * sx[i] + dy[j] * sy[i] + (LL) i * k;
                LL div1 = dx[j] * X + dy[j] * Y - lft;
                if (coeff == 0) {
                    if (div1 <= 0) continue;
                    calc_range(INF, -INF);
                    break;
                }
                else if (coeff < 0) calc_range(-INF, 1.0 * div1 / coeff);
                else calc_range(ceil(1.0 * div1 / coeff), INF);
            }
            calc_range(0, INF);
            if (l - r > eps) continue;
            ans = min(ans, (LL) ceil(l) * n + i);
        }
        printf("%lld\n", ans >= INF ? -1 : ans);
    }

    return 0;
}

蒟蒻犯的若至错误

  • 计算时直接取整数,导致出现两个非 \(0\) 解时取到不合法解
  • eps 过大
posted @ 2024-12-12 20:57  是一只小蒟蒻呀  阅读(2)  评论(0编辑  收藏  举报