BestCoder Round #49 ($)

Untitled

Accepts: 504
Submissions: 1542
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 65536/65536 K (Java/Others)
Problem Description

There is an integer aaa and nnn integers b1,…,bnb_1, \ldots, b_nb1,,bn. After selecting some numbers from b1,…,bnb_1, \ldots, b_nb1,,bn in any order, say c1,…,crc_1, \ldots, c_rc1,,cr, we want to make sure that a mod c1 mod c2 mod… mod cr=0a \ mod \ c_1 \ mod \ c_2 \ mod \ldots \ mod \ c_r = 0a mod c1 mod c2 mod mod cr=0 (i.e., aaa will become the remainder divided by cic_ici each time, and at the end, we want aaa to become 000). Please determine the minimum value of rrr. If the goal cannot be achieved, print −1-11 instead.

Input

The first line contains one integer T≤5T \leq 5T5, which represents the number of testcases.

For each testcase, there are two lines:

  1. The first line contains two integers nnn and aaa (1≤n≤20,1≤a≤1061 \leq n \leq 20, 1 \leq a \leq 10^61n20,1a106).

  2. The second line contains nnn integers b1,…,bnb_1, \ldots, b_nb1,,bn (∀1≤i≤n,1≤bi≤106\forall 1\leq i \leq n, 1 \leq b_i \leq 10^61in,1bi106).

Output

Print TTT answers in TTT lines.

Sample Input
2
2 9
2 7
2 9
6 7
Sample Output
2

-1

解析:对于一组可能的答案cc,如果先对一个觉小的cici取模,再对一个较大的cjcj取模,那么这个较大的cjcj肯定是没有用的。因此最终的答案序列中的c肯定是不增的。那么就枚举选哪些数字,并从大到小取模看看结果是否是0就可以了。时间复杂度O(2n)O(2^n)

我做的时候是暴力枚举的所有排列,超时了。。。

代码:

#include<iostream> #include<cstdio> #include<string.h> #include<algorithm> #include<queue> using namespace std; int main() {     int n,T,a,b[25],c[25];     cin>>T;     while(T--){         cin>>n>>a;         for(int i=0;i<n;i++)             cin>>b[i];         sort(b,b+n);         int flag=0,id=n;         for(int i=0;i<n;i++)         if(a%b[i]==0){             cout<<"1"<<endl;             flag=1;             break;         }         if(flag==1)continue;         do{             int newa=a;             for(int i=0;i<n;i++)             {                 newa%=b[i];                 if(newa==0){                     if(id>i)id=i;                     flag=1;                     break;                 }             }         }while(next_permutation(b,b+n));         if(flag)cout<<id+1<<endl;         else cout<<"-1"<<endl;     } return 0; }

其实按照解析,不用枚举所有排列,只需从大到小排序,然后依次枚举一下就好了

#include<iostream> #include<stdio.h> #include<cmath> #include<algorithm> #define INF 999999999 using namespace std; bool cmp(int a,int b) {     return a>b; } int solve(int a,int b[],int n) {     int ss=INF;     int flag;   for(int i=1; i<=n; i++)     {         int temp=a;         flag = 0;         for(int j=i; j<=n; j++,flag++)             if(temp==0) break;             else                 temp=temp%b[j];         if(temp==0)             ss=min(ss,flag);     }     return ss==INF?-1:ss; } int main() {     int T;     int n,a;     int b[21];     scanf("%d",&T);     while(T--)     {         scanf("%d%d",&n,&a);         for(int i=1; i<=n; i++)             scanf("%d",&b[i]);         sort(b+1,b+n+1,cmp);         printf("%d\n",solve(a,b,n));     }     return 0; }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值