给你一个有N个数的集合S和一个数X,判断是否存在S的一个子集,子集里的数的最小公倍数正好是X。
第一行是数据组数T。 接下来有多组数据,每组数据包含两行: 第一行有2个数N和X,1<=N<=100000 ,X<=10^9。 第二行给出N个数,1<=S[i]<=10^9。
对于每一组数据,输出一行"Case #X: Y",X是第几组数据,Y是Yes或No。
2 4 20 2 3 4 5 3 61 3 4 5
Case #1: Yes Case #2: No 思路:先把X的质因数全部找出来,然后在N个数里面枚举s[i]的质因数是不是小于等于X的质因数,如果是就可以更新答案ans[i],ans[i]代表第i个质因数的个数。#include <iostream> #include <algorithm> #include <cmath> #include <cstring> #include <queue> #include <cstring> #include <string> #include <vector> #include <cstdio> using namespace std; const int maxn = 100010; int a[maxn]; int okx[maxn]; int okxx[maxn]; int ans[maxn]; int s[maxn]; int main() { int T,cas=0,n,x; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&x); int flag = 0; for(int i=0; i<n; i++) { scanf("%d",&a[i]); flag = a[i]==x; } if(flag) { printf("Case #%d: Yes\n",++cas); continue; } memset(okx,0,sizeof(okx)); int sqrtx = sqrt(x); int m = x; int top = 0; for(int i=2; i<=sqrtx; i++) { if(m%i==0) { okxx[top] = i; okx[top]++; m/=i; while(m%i==0) { okx[top]++; m/=i; } top++; } } if(m>1) { okxx[top] = m; okx[top++] = 1; } memset(ans,0,sizeof(ans)); for(int i=0; i<n; i++) { for(int k=0;k<top;k++)s[k]=0; flag = 0; int m = a[i]; for(int j=0; j<top; j++) { while(m%okxx[j]==0) { s[j]++; m/=okxx[j]; } } if(m>1) { flag = 1; } for(int j=0; j<top; j++) { if(s[j]>okx[j]) { flag = 1; break; } } if(!flag) { for(int j=0; j<top; j++) { ans[j] = max(ans[j],s[j]); } } } flag = 1; for(int j=0;j<top;j++) { if(ans[j]!=okx[j]) { flag = 0; break; } } printf("Case #%d: %s\n",++cas,flag?"Yes":"No"); } return 0; }
还有一种方法就是直接把能被X整除的数都s[i]都单独拿出来,在这些数中找是否公倍数为X.#include<iostream> #include<algorithm> #include<cstring> #include<cstdio> #include<cmath> using namespace std; const int maxn = 100010; int s[maxn]; int ss[maxn]; int vis[maxn]; int flag,x,n,top; int gcd(int a,int b) { return b==0?a:gcd(b,a%b); } void dfs(__int64 ans,__int64 ok) { if(ans == x) { flag = 1; return ; } if(ans > x) return; if(flag) return ; for(int i=0; i<top; i++) { if(vis[i]) continue; int m = gcd(ss[i],ok); vis[i] = 1; dfs(ans*ss[i]/m,m); vis[i] = 0; if(flag) break; } return ; } int main() { int T,cas = 0; scanf("%d",&T); while(T--) { flag = 0; scanf("%d%d",&n,&x); for(int i=0; i<n; i++) scanf("%d",&s[i]); memset(vis,0,sizeof(vis)); for(int i=0; i<n; i++) if(x%s[i]!=0) vis[i] = 1; top = 0; for(int i=0; i<n; i++) if(!vis[i]) ss[top++] = s[i]; memset(vis,0,sizeof(vis)); for(int i=0; i<top; i++) { if(flag) break; __int64 ans = 1; if(!vis[i]) { vis[i] = 1; dfs(ans*ss[i],ss[i]); ///vis[i] = 0; } } printf("Case #%d: %s\n",++cas,flag?"Yes":"No"); } return 0; }