题解-[省选联考 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\)

思路:

\(\forall 0\leq i\leq m-1,|x_i'|+|y_i'|\leq k\) \(\iff\) \(\sum \limits_{i=0}^{m-1}| x_i'| + \sum \limits_{i=0}^{m-1}|y_i'| \le m \times k\)

移项可得 \(\sum \limits_{i=0}^{m-1} x_i'=x - \sum \limits_{i=0}^{m-1} x_{i \bmod n}\)\(\sum \limits_{i=0}^{m-1} y_i'=y - \sum \limits_{i=0}^{m-1} y_{i \bmod n}\)

所以题目的限制条件就变成了 $ |x - \sum \limits_{i=0}^{m-1} x_{i \bmod n}| + |y - \sum \limits_{i=0}^{m-1} y_{i \bmod n}| \le m \times k$。

发现这个下标为 \(i \bmod n\),那不妨记 \(m = t\times n + q\)

那么原式子可以变成 $ |x - \sum \limits_{i=0}^{n-1} x_i \times t - \sum \limits_{i=0}^{q-1} x_i| + |y - \sum \limits_{i=0}^{n-1} y_i \times t - \sum \limits_{i=0}^{q-1} y_i| \le (t\times n + q) \times k$。

因为 \(q \in [0 , n-1]\),那么直接枚举 \(q\),原式就是一个关于 \(t\) 的不等式,直接解即可,时间复杂度 \(O(n)\)

代码:

#include<bits/stdc++.h>
#define rep(i,a,n) for(int i=(a);i<=(n);i++)
#define per(i,a,n) for(int i=(n);i>=(a);i--)
#define pb push_back
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<ll,ll> pll;

template<typename T> 
inline void pr(T x,bool op=false){
    x<0?x=-x,putchar('-'):0;
    static short sta[25],top(0);
    do sta[top++]=x%10,x/=10; while(x);
    while(top) putchar(sta[--top]|48);
    op?putchar('\n'):putchar(' ');
} 
template<class T> void rd(T &x){
    char c; bool f = 0;
    while(((c = getchar()) < '0' || c > '9') && c != '-');
    if(c == '-'){f = 1; c = getchar();}
    x = c - '0';
    while((c = getchar()) >= '0' && c <= '9')x = x * 10 + c - '0';
    if(f) x = -x;
}

const int maxn=1e6+10;
const ll inf=4e18;
int n,k,x,y,a[maxn],b[maxn];
ll prea,preb,sa,sb;
inline pll calc(ll x,ll y){
    if(!x){
        if(y>=0) return {-inf,inf};  
        else return {inf,-inf};
    } 
    else{
        if(x<0){
            if(!y)  return {0,inf};
            if(y<0) return {((-y)+(-x)-1)/(-x),inf};
            if(y>0) return {-(y/(-x)),inf};
        }
        if(x>0){
            if(!y)  return {-inf,0};
            if(y<0) return {-inf,-(((-y)+x-1)/x)}; 
            if(y>0) return {-inf,y/x};
        }
    }
    return {-inf,inf};
}
inline void solveall(){
    ll ans=inf;
    rep(i,0,n-1){
        ll l=-inf,r=inf;
        pll now;
        now=calc(-sa-sb-1ll*n*k,1ll*i*k-x-y+prea+preb); l=max(l,now.fi); r=min(r,now.se);
        now=calc(-sa+sb-1ll*n*k,1ll*i*k-x+y+prea-preb); l=max(l,now.fi); r=min(r,now.se);
        now=calc( sa-sb-1ll*n*k,1ll*i*k+x-y-prea+preb); l=max(l,now.fi); r=min(r,now.se);
        now=calc( sa+sb-1ll*n*k,1ll*i*k+x+y-prea-preb); l=max(l,now.fi); r=min(r,now.se);
        if(l<=r && r>=0) ans=min(ans,max(l,0ll)*n+i);
        prea+=a[i]; preb+=b[i];
    }
    if(ans==inf) ans=-1;
    pr(ans,1);
}
inline void solve(){
    sa=sb=prea=preb=0;
    rd(n); rd(k); rd(x); rd(y);
    rep(i,0,n-1){
        rd(a[i]),rd(b[i]);
        sa+=a[i]; sb+=b[i];
    } 
    if(!x && !y) pr(0,1);
    else solveall();   
}
signed main(){
    int _=1;
    rd(_);
    while(_--) solve();
}
posted @   lying_up  阅读(111)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示