1 条题解
-
0
思路
贪心+二分
根据题意我们可以对数组做任意次操作,去求最大的,因为k的值是固定的,所以我们尽量让数组的值变小,小到k可以覆盖他,这样就可以最大限度的增大的值
所以我们的有效操作就是让 ,操作累加起来就是 = % ; 这时候可以发现对的操作相当于求最大公约数的辗转相除,我们只需要求出来数组中元素的最大公约数, 设其为便是数组a操作后的最小数,再利用操作1,2让的倍数去覆盖包含的区间即可 对于每个数 ,包含的区间满足单调递增,符合二分性质,所以我们可以用二分来求解答案
#include<bits/stdc++.h> using namespace std; int a[200005]; int n,k; bool check(int x,int gcd) { int m=x/gcd;//当前数x所覆盖的区间 if(m>n) m=n;//最大只能覆盖n个区间 if(x>=k+m)//覆盖区间+k便是范围 { return 1; } return 0; } int main() { int t; cin >> t;//相当于scanf while(t--) { cin >>n >>k; int gd=0; for(int i=1;i<=n;i++) { cin >> a[i]; } if(n==1)//特判n==1的情况 { if(k<=a[1]) { cout <<k-1<<'\n'; } else cout<<k<<'\n'; continue; } for(int i=1;i<=n;i++) { gd=__gcd(a[i],gd); } int ans=0; if(gd==1)//如果数组a的gcd等于1则填补区间为0-n-1; { cout <<n+k-1<<'\n';//相当于printf } else { int l=1,r=n+k+10;//二分范围 int mid; while(l<=r) { mid=(l+r)/2; if(check(mid,gd))//如果满足条件 缩小 r=mid-1; else//不满足条件,增大 l=mid+1; } cout <<l<<'\n'; } } }
- 1
信息
- ID
- 1014
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- (无)
- 递交数
- 21
- 已通过
- 1
- 上传者