『题解』Luogu P8550 冬之花
题目大意
给定 \(n\) 个数 \(a_1, a_2, \ldots, a_n\),再给定一个非零数 \(x\)。
你需要进行 \({10}^{100}\) 次操作,每次操作,你需要选定一个下标 \(i\)(\(1 \le i \le n\)),然后给 \(x\) 加上 \(a_i\)。
你需要保证,在每次操作后,新的 \(x\) 值都不能为 \(0\)。
请判断你能否完成这 \({10}^{100}\) 次操作。
多组数据。
思路
我们可以尽量不让 \(x\) 变为 \(0\),因为很多情况 \(x\) 的值都不能变为 \(0\),方便判断。
先考虑只用某一个操作数,让 \(x\) 一直加上它。
设这个操作数为 \(y\)。
-
\(y=0\),\(x+y\) 还是等于 \(x\),可以避免变为 \(0\)。
-
\(y\) 与 \(x\) 同号,加的越多,离 \(0\) 越远。
-
\(y\) 与 \(x\) 异号,这时只需判断 \(x\) 加上若干个 \(y\) 之后会不会变为 \(0\)。
如果这些情况都没有出现,那么我们就只能考虑用多个不同的数来避开 \(0\) 了。
可以想到:若有任意两个不同的操作数,那么不管 \(x\) 是多少,都可以避开 \(0\)。
事实证明这个想法是正确的。可以自证一下。
于是只需要一个 \(flag\),记录能否避开 \(0\) 即可。
代码
#include <iostream>
using namespace std;
template<typename T=int>
inline T read(){
T X=0; bool flag=1; char ch=getchar();
while(ch<'0' || ch>'9'){if(ch=='-') flag=0; ch=getchar();}
while(ch>='0' && ch<='9') X=(X<<1)+(X<<3)+(ch^48),ch=getchar();
if(flag) return X;
return ~(X-1);
}
const int N=10;
int t,n,x;
int a[N];
bool flag;
int main(){
t=read();
while(t--){
n=read(),x=read();
flag=0;
for(int i=1; i<=n; i++){
a[i]=read();
if(x*a[i]>=0 || x%a[i]!=0)
flag=1;
}
for(int i=1; i<=n; i++)
for(int j=i+1; j<=n; j++)
if(a[i]!=a[j])
flag=1;
puts(flag ? "Yes" : "No");
}
return 0;
}