『题解』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;
}
posted @ 2022-09-24 20:41  仙山有茗  阅读(44)  评论(0编辑  收藏  举报