给定一个长度为N的数组,以及一个乘积值B,每次只能对一个数增大或减少一个单位,问最少多少次使得数组乘积为B
【思路】
要使得调整的次数最少,那么最开始调整的那个数字,应该是最小的数。
贪心策略:选最小的数调整,其它部分数乘积最大(自己需要调整的偏移值就尽可能小)
先对原先数组从小到大排序。
对于k 如果 B%k==0 =》 B=B/k 即如果能整除,那么直接整除
如果B%k!=0 =》 不能整除 那么 a[k]-- (即调整一次 因为最差情况下a[k] 调整为1 那么一定能整除)
直到k=>N
int fun(vector<int> arr,int b) { int count=0; for(int i=0;i<arr.size();i++) { if(b%arr[i]==0) { b/=arr[i]; } else { arr[i]--; count++; i--; } } }
【特殊连续递增序列】
给定一个序列,求这样的一个完美序列,是一个连续的子序列,并且序列中每一个数都大于等于前面所有数字之和。
基本思路:
滑动窗口,left=1 right=1 维护一个sum变量表示窗口中前面k-1个的和:
若当前窗口满足 arr[right]>=sum 那么 更新res sum+=arr[right] 同时right++ 若当前窗口不满足 窗口左边缩减 同时 sum-=arr[left] 那么left++易错点:
原本思路是 add[k]存放前面k个数字之和,那么求解区间直接相减: add[right]-add[left-1] =》 add会加法溢出
#include<iostream> #include<vector> using namespace std; int main() { int n; cin>>n; int k; for(int i=0;i<n;i++) { cin>>k; vector<long long> arr(k+1,0); arr[0]=0; //完成初始化 for(int j=1;j<=k;j++) cin>>arr[j]; int left=1; int right=1; long long sum=0; //滑动窗口内之和 int ans=0; while(right<=k) { if(arr[right]>=sum) //满足 { ans=max(ans,right-left+1); //记录下符合要求窗口的长度 sum+=arr[right]; right++; //,满足连续递增 } else { sum-=arr[left]; left++; } } cout<<ans<<endl; } }