Problem Description
There is an integer a and n integers b1,…,bn. After selecting some numbers from b1,…,bn in any order, say c1,…,cr, we want to make sure that a mod c1 mod c2 mod… mod cr=0 (i.e., a will become the remainder divided by ci each time, and at the end, we want a to become 0). Please determine the minimum value of r. If the goal cannot be achieved, print −1 instead.
Input
The first line contains one integer T≤5, which represents the number of testcases.
For each testcase, there are two lines:
1. The first line contains two integers n and a (1≤n≤20,1≤a≤106).
2. The second line contains n integers b1,…,bn (∀1≤i≤n,1≤bi≤106).
For each testcase, there are two lines:
1. The first line contains two integers n and a (1≤n≤20,1≤a≤106).
2. The second line contains n integers b1,…,bn (∀1≤i≤n,1≤bi≤106).
Output
Print T answers in T lines.
Sample Input
2
2 9
2 7
2 9
6 7
Sample Output
2
-1
dfs题:不过这题很容易超时。要注意剪枝。剪枝地方我会在代码中说明,看代码就可以了。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,b[30],r,mn;
int v[30];
void dfs(int k,int a)
{
int i,s;
for (i=1;i<=n;i++)
{
if (!v[i])
{
s=a%b[i];
if (s==0) {r=min(r,k+1);return ;}
if (s<mn) continue; //剪枝。如果s比这些数中最小值还小,那么s就不可能为0.
v[i]=1;
dfs(k+1,s);
v[i]=0;
}
}
return ;
}
int main()
{
int t,i,a,c,d;
scanf("%d",&t);
while (t--)
{
r=30;
scanf("%d%d",&n,&a);
c=n;
i=1;
mn=1000000;
while (c--)
{
scanf("%d",&d);
if (d>a) continue; //剪枝。a模比a大的数还是a,就可以不用管。
if (a%d==0) r=1; //剪枝。如果a是这些数中一些数的倍数,那么最小值就是一。
b[i++]=d;
mn=min(mn,d);
}
n=i-1;
sort(b+1,b+i);
if (r==1) {printf("1\n");continue;}
memset(v,0,sizeof(v));
dfs(0,a);
if (r==30) printf("-1\n");
else printf("%d\n",r);
}
}
浙公网安备 33010602011771号