P10217 [省選聯考 2024] 季風
[省選聯考 2024] 季風
題目背景
生活在二維平面的小 X 準備拜訪小 Y,但由於氣候的變化,平面上颳起了季風。小 X 想知道季風的影響下,TA 至少要多少天能夠到達小 Y 的家,但小 X 也是第一次遇見這種怪事,所以請精通演算法的你來幫忙。
題目描述
給定 \(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\)。
輸入格式
本題有多組測試資料。輸入的第一行一個整數 \(T\) 表示測試資料組數。
對於每組測試資料,
- 第一行四個整數 \(n,k,x,y\);
- 接下來 \(n\) 行,第 \(i\) 行兩個整數 \(x_{i-1},y_{i-1}\)。
輸出格式
對於每組測試資料輸出一行一個整數,如果存在滿足題意的 \(m\),輸出其最小可能值,否則輸出 \(-1\)。
歡樂補題捏
首先我們來整理一下式子:
我們將n無限迴圈,則原式可化為:
$ mx_i'$ =\(x\) - \(\sum \limits_{i=0}^{m-1} x_i\)
$ my_i'$ =\(y\) - \(\sum \limits_{i=0}^{m-1} y_i\)
|\(x\) -
\(\sum \limits_{i=0}^{m-1} x_i\)| +
|\(y\) -
\(\sum \limits_{i=0}^{m-1} y_i\)| \(<=\) \(mk\)
把絕對值拆了之後:
\(\sum \limits_{i=0}^{m-1} (x_i+y_i+k)\) >=\(X+Y\)
\(\sum \limits_{i=0}^{m-1} (x_i-y_i+k)\) >=\(X-Y\)
\(\sum \limits_{i=0}^{m-1} (-x_i+y_i+k)\) >=\(-X+Y\)
\(\sum \limits_{i=0}^{m-1} (-x_i-y_i+k)\) >=\(-X-Y\)
求出同時滿足這四個條件的m
記\(s_x\)=\(\sum \limits_{i=1}^{x} (x_i+y_i+k)\)
\(sum=s_n\)
考慮列舉每個1<=i<=n:
記 \(l_i\)為最後一位取在\(i\)時m的下界,\(r_i\)為上界
則\((l_i /r_i=X+Y-S_i)/sum\)
\(l_i/r_i\)取決於分母的符號
特殊的,當sum=時,若\(S_i>=X+Y\)則任取,否則不能
同理,對上面提到過的四種情況做相同的討論,得出\(l,r\)
最後統計答案時,若滿足\(l_i<=r_i\)
則\(ans=min(ans,l_i*n+i)\)
然後這題就做完了
Code
#include<bits/stdc++.h>
#define int long long
const int N=1e6+5;
const int inf=1e18;
using namespace std;
int x[N],y[N],s[N],l[N],r[N];
int n,k,X,Y;
void calc(int fx,int fy)
{
int pos=fx*X+fy*Y;
for(int i=1;i<=n;i++)
{
s[i]=s[i-1]+x[i]*fx+y[i]*fy+k;
}
if(!s[n])
{
for(int i=1;i<=n;i++)
{
if(s[i]<pos)r[i]=-1;
}
return ;
}
else
{
for(int i=1,fz,fm=s[n];i<=n;i++)
{
fz=pos-s[i];
if(s[n]>0)
{
if(fz>0)//ans_l=(pos-s[i])/s[n] (bigger)
{
l[i]=max(l[i],(fz%fm? fz/fm+1 : fz/fm));
}
}
else //ans_r=(pos-s[i])/s[n] (lower)
{
if(fz>0)//ans_r<0
{
r[i]=-1ll;
}
else
{
r[i]=min(r[i],fz/fm);
}
}
}
}
}
void work()
{
cin>>n>>k>>X>>Y;
for(int i=1;i<=n;i++)
{
scanf("%lld%lld",&x[i],&y[i]);
l[i]=0;
r[i]=inf;
}
if(!X&&!Y)
{
printf("%lld\n", 0ll);
return;
}
int ans=inf;
calc(1,1);calc(1,-1);calc(-1,1);calc(-1,-1);
for(int i=1;i<=n;i++)
{
if(l[i]<=r[i])
ans=min(ans,l[i]*n+i);
}
printf("%lld\n",ans==inf? -1ll : ans);
}
#undef int
int main()
{
//freopen("P10217_1.in","r",stdin);//freopen("P10217.out","w",stdout);
int T;
cin>>T;
while(T--)
{
work();
}
}