标签:
题意:给一个数a和n个数b1,b2,...,bn。
从n个数中选择一些数重新排列成c1,c2,...,cm使得a%c1%c2%...%cm=0.
如果能选出则输出最少需要几个数,否则输出-1。
分析:
首先很重要的一点就是 “一定是先除大的数再除小的数”
因为如果先除小的数x,则取模的数一定是在0到x-1中,再除大于x的数是没意义的。
即选出的一列数是非递增序列。
由于n最多只有20个,简单的2^n的搜索即可搞定了。
通过这题发现hdu oj的一个bug
就是排序的时候不能手写整数的cmp使其逆序排列,否则g++判RE,c++判wa。
有两种写法,其实思路一样,处理手法有一点区别:
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #include<cstdlib> 6 #include<cmath> 7 #include<vector> 8 #include<queue> 9 #include<map> 10 #include<set> 11 #define eps 10e-13 12 13 using namespace std; 14 15 typedef long long ll; 16 17 int b[25],v[25],n,a,c,ans; 18 bool vis[25]; 19 20 void dfs(int cur) 21 { 22 if(cur==-1) 23 { 24 int t = a; 25 for(int i=0;i<c;i++) 26 t%=v[i]; 27 if(t==0) ans = min(ans,c); 28 return; 29 } 30 vis[cur] = true; 31 v[c++] = b[cur]; 32 dfs(cur-1); 33 vis[cur] = false; 34 c--; 35 dfs(cur-1); 36 } 37 38 int main() 39 { 40 int T; 41 scanf("%d",&T); 42 while(T--) 43 { 44 scanf("%d%d",&n,&a); 45 for(int i=0;i<n;i++) 46 scanf("%d",&b[i]); 47 sort(b,b+n); 48 c = 0; 49 memset(vis,0,sizeof(vis)); 50 ans = 30; 51 dfs(n-1); 52 printf("%d\n",ans==30?-1:ans); 53 } 54 return 0; 55 }
更简洁:
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #include<cstdlib> 6 #include<cmath> 7 #include<vector> 8 #include<queue> 9 #include<map> 10 #include<set> 11 #define eps 10e-13 12 13 using namespace std; 14 15 typedef long long ll; 16 17 int b[30],v[30],n,a,c,ans; 18 19 void dfs(int cur,int x,int len) 20 { 21 if(x==0) ans = min(ans,len); 22 if(cur==-1) return; 23 dfs(cur-1,x,len); 24 dfs(cur-1,x%b[cur],len+1); 25 } 26 27 int main() 28 { 29 int T; 30 scanf("%d",&T); 31 while(T--) 32 { 33 scanf("%d%d",&n,&a); 34 for(int i=0;i<n;i++) 35 scanf("%d",&b[i]); 36 sort(b,b+n); 37 c = 0; 38 ans = 30; 39 dfs(n-1,a,0); 40 if(ans<30) printf("%d\n",ans); 41 else printf("-1\n"); 42 } 43 return 0; 44 }
标签:
原文地址:http://www.cnblogs.com/hadis-yuki/p/4695415.html