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 ");continue;} memset(v,0,sizeof(v)); dfs(0,a); if (r==30) printf("-1 "); else printf("%d ",r); } }