没想到啊,再见OI之后还会写博客。
ZXB啊ZXB,要努力练ACM啊。
5.Monopoly
p
r
e
[
i
]
pre[i]
pre[i] 为
a
a
a的前缀和
S
u
m
Sum
Sum为数组总和
若有解则存在
M
M
M使得
p
r
e
[
i
]
+
M
∗
S
u
m
=
=
x
pre[i]+M*Sum==x
pre[i]+M∗Sum==x
也就是说
p
r
e
[
i
]
≡
x
(
m
o
d
S
u
m
)
pre[i] \equiv x \ (mod\ \ Sum)
pre[i]≡x (mod Sum)
然后对
S
u
m
Sum
Sum分情况讨论就好,正数、负数,分别找小于
x
x
x的最大的
p
r
e
[
i
]
pre[i]
pre[i]和大于
x
x
x的最小的
p
r
e
[
i
]
pre[i]
pre[i]
最后
S
u
m
=
0
Sum=0
Sum=0的情况特判一下就好了
有一说一,口胡还是蛮简单的,就是细节有点烦人qwq(没办法,谁叫我菜呢 )
代码有点丑,a了就不想改了qwq
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=1e6+5;
int N,M,Sum,tot,a[maxn];
map <int,int> mn;
map <int,int> :: iterator iter;
struct node{int id,w;};
inline bool operator <(node a,node b) {
if (Sum>0) return a.w<b.w||a.w==b.w&&a.id>b.id;
else return a.w<b.w||a.w==b.w&&a.id<b.id;
}
vector <node> mol[maxn];
inline int read() {
int ret=0,f=1;
char ch=getchar();
for (; !isdigit(ch); ch=getchar()) if (ch=='-') f=-f;
for (; isdigit(ch); ch=getchar()) ret=ret*10+ch-48;
return ret*f;
}
void Find1(int x) {//找小于x的最大的pre[i]
int Ans=-1;
int ID=mn[(x%Sum+Sum)%Sum];
int L=0,R=mol[ID].size()-1;
while (L<=R) {
int Mid=L+(R-L>>1);
if (mol[ID][Mid].w<=x) Ans=Mid,L=Mid+1;
else R=Mid-1;
}
if (~Ans) printf("%lld\n",(x-mol[ID][Ans].w)/Sum*N+mol[ID][Ans].id);
else puts("-1");
}
void Find2(int x) {//大于x的最小的pre[i]
int Ans=-1;
Sum=-Sum;
int ID=mn[(x%Sum+Sum)%Sum];
int L=0,R=mol[ID].size()-1;
while (L<=R) {
int Mid=L+(R-L>>1);
if (mol[ID][Mid].w>=x) Ans=Mid,R=Mid-1;
else L=Mid+1;
}
if (~Ans) printf("%lld\n",(mol[ID][Ans].w-x)/Sum*N+mol[ID][Ans].id);
else puts("-1");
Sum=-Sum;
}
signed main() {
for (int T=read(); T--; mn.clear()) {
N=read(),M=read(),a[0]=0;
for (int i=1; i<=N; ++i) a[i]=a[i-1]+read();//a就是pre
Sum=a[N];
if (Sum==0) {
for (int i=1; i<=N; ++i) if (mn[a[i]]==0) mn[a[i]]=i;
for (int i=1; i<=M; ++i) {
int x=read();
if (x==0)
puts("0");
else
if (mn[x]!=0) printf("%lld\n",mn[x]);
else puts("-1");
}
continue;
} else {
bool flg=(Sum>0);
if (Sum<0) Sum=-Sum;
tot=0;
for (int i=1,tmp; i<=N; ++i) {//离散
tmp=(a[i]%Sum+Sum)%Sum;
if (mn[tmp]==0) mn[tmp]=++tot;
mol[mn[tmp]].push_back((node){i,a[i]});
}
if (!flg) Sum=-Sum;
for (iter=mn.begin(); iter!=mn.end(); iter++) {
sort(mol[mn[iter->first]].begin(),mol[mn[iter->first]].end());
}
for (int i=1; i<=M; ++i) {
int x=read();
if (x==0)
puts("0");
else
if (flg) Find1(x);else Find2(x);
}
for (iter=mn.begin(); iter!=mn.end(); iter++) {
mol[mn[iter->first]].clear();
}
}
}
return 0;
}