本人主要用的是DFS搜索,有几处剪枝:
1.先检查a[n]中是否有a[i]==x,有直接输出Possible,结束程序;
2.再检测x是否为质数,如果是,输出Impossible,结束程序,否则继续;
3.另开数组b[n],记录a[n]中可以被x整除的数,这是因为能够构成LCM=x的数,这些数一定是x的因子,最后调用DFS搜索(可以剪掉挺多的数据)。
代码如下:
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll; //一定要用long long,否则会溢出,因为这个WA了好几次
ll a[55],b[55],cnt,n,x;
ll gcd(ll x,ll y)
{
if(x>y) swap(x,y);
ll r=y%x;
while(r)
y=x,x=r,r=y%x;
return x;
}
bool dfs(int pos,ll num) //从当前位置pos开始搜索,当前LCM=num(num初始为b[pos])
{
for(int i=pos+1;i<cnt;i++) //循环以pos+1为起点
{
if(b[pos]%b[i]==0||b[i]%b[pos]==0) continue; //DFS剪枝,去除本身是b[pos]的因子,或b[pos]是其因子的数,因为这些数求LCM后要么为b[pos],要么为b[i]
if(num%b[i]==0||b[i]%num==0) continue; //同理
ll temp=num*b[i]/gcd(num,b[i]);
if(temp>x) continue;
else if(temp==x) return 1;
else if(dfs(i,temp)) return 1;
}
return 0;
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
cin>>x;
cnt=1;
for(int i=1;i<=n;++i)
{
if(x%a[i]==0)
b[cnt++]=a[i];
if(x==a[i])
{
cout<<"Possible\n";
return 0;
}
}
if(cnt==1) { cout<<"Impossible\n"; return 0; } //如果a[n]中没有x的因子,就可以直接结束了
bool flag=0;
for(int i=2;i<=sqrt(x);++i)
if(x%i==0)
{
flag=1;
break;
}
if(!flag) //prime number
cout<<"Impossible\n";
else
{
sort(b+1,b+cnt); ;
bool f=0;
for(int i=1;i<cnt;++i)
{
if(dfs(i,b[i]))
{
cout<<"Possible\n";
return 0;
}
}
cout<<"Impossible\n";
}
return 0;
}
注意:涉及乘法要小心数据溢出!