2 2 9 2 7 2 9 6 7
2 -1
大致题意:
20个数,求选出最少的数然后这些数的某种排列可以连续模a得到0
思路:显然先模大的数,再模小的数,否则没意义
所以状压枚举子集,1<<20 = 100w 然后dp,用了lowbit优化了一下
//#pragma comment(linker, "/STACK:1024000000,1024000000") #include <iostream> #include <cstring> #include <cmath> #include <queue> #include <stack> #include <map> #include <set> #include <string> #include <vector> #include <cstdio> #include <ctime> #include <bitset> #include <algorithm> #define SZ(x) ((int)(x).size()) #define ALL(v) (v).begin(), (v).end() #define foreach(i, v) for (__typeof((v).begin()) i = (v).begin(); i != (v).end(); ++ i) #define REP(i,n) for ( int i=1; i<=int(n); i++ ) using namespace std; typedef long long ll; #define X first #define Y second typedef pair<int,int> pii; template <class T> inline bool RD(T &ret) { char c; int sgn; if (c = getchar(), c == EOF) return 0; while (c != '-' && (c<'0' || c>'9')) c = getchar(); sgn = (c == '-') ? -1 : 1; ret = (c == '-') ? 0 : (c - '0'); while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0'); ret *= sgn; return 1; } template <class T> inline void PT(T x){ if (x < 0) { putchar('-'); x = -x; } if (x > 9) pt(x / 10); putchar(x % 10 + '0'); } const int N = 22; int m[25]; int dp[1<<N]; int sum[1<<N]; int inline lowbit(int x){ return x & -x; } bool cmp(int a,int b){ return a > b; } int vs[1<<N]; int main(){ for(int i = 0; i<= 20;i++) vs[1<<i] = i; int T; cin>>T; while(T--){ memset(sum,0,sizeof(sum)); int n,a; RD(n),RD(a); REP(i,n) RD(m[i-1]); sort(m,m+n); REP(i,n) { dp[1<<(i-1)] = a%m[i-1]; sum[1<<(i-1)] = 1; } int ans = 100; for(int i = 1;i < (1<<n);i++){ int cur = i; if(sum[cur] == 0){ sum[cur] = sum[cur-lowbit(cur)] + sum[lowbit(cur)]; dp[cur] = dp[cur-lowbit(cur)]%m[vs[lowbit(cur)]]; } if( dp[cur] == 0) ans = min(ans,sum[cur]); } if(ans == 100) puts("-1"); else printf("%d\n",ans); } }