当前位置:   article > 正文

小美的区间删除

小美的区间删除

因为结尾0的个数取决于有多少对 ( 2 , 5 ) (2,5) (2,5) 相乘,那么对于下面例题,解题思路为:

1、将每个数字中的2和5剥离出来,然后用两个数组进行记录,然后其子数 ( 2 , 5 ) (2,5) (2,5)组成对至少为k个。

2、遍历每一个子数组然后计算:会发现超时:

​ 下面公式推导一下:
t o t l e 2 − t w o > = k 、 t o t l e 5 − f i v e > = k 由于 t w o = f 2 [ j ] − f 2 [ i ] ; 这里的 f 为数组 2 剥离的前缀和 由于 f i v e = f 5 [ j ] − f 5 [ i ] ; 上述 i , j 为子数组 ( i , j − 1 ) 。因此我们固定 i ,由于前缀和是递增的,因此可以使用二分,找到右边界。 推到出: t o t l e − ( f [ j ] − f [ i ] ) > = k ; t o t l e + f [ i ] − k > = f [ j ] ; totle2-two>=k、totle5-five>=k\\ 由于two = f2[j]-f2[i];这里的f为数组2剥离的前缀和\\ 由于five = f5[j]-f5[i];\\ 上述i,j 为子数组(i,j-1)。因此我们固定i,由于前缀和是递增的,因此可以使用二分,找到右边界。\\ 推到出: totle-(f[j]-f[i])>=k;\\ totle+f[i]-k>=f[j]; totle2two>=ktotle5five>=k由于two=f2[j]f2[i];这里的f为数组2剥离的前缀和由于five=f5[j]f5[i];上述i,j为子数组(i,j1)。因此我们固定i,由于前缀和是递增的,因此可以使用二分,找到右边界。推到出:totle(f[j]f[i])>=k;totle+f[i]k>=f[j];
那么讨论一下边界问题:

二分 f [ j ] f[j] f[j]返回的是第一个大于 f [ j ] f[j] f[j]值的位置,但是这时就不符合 t o t l e + f [ i ] − k > = f [ j ] totle+f[i]-k>=f[j] totle+f[i]k>=f[j]了,因此减去1,此时是刚好的。

#include <iostream>
#include <set>
#include <vector>
using namespace std;

// 剥离n中存在几个base的因子。如果是2,和5的话,
// 就是base中存在多少个2相乘和多少个5相乘
int factor(int n, int base){
    int ans = 0;
    while (n and !(n%base)) {
        n/=base;
        ans++;
    }
    return ans;
}

int base_right(const vector<int>& vec, int value){
    int left = 0;
    int right = vec.size()-1;
    int res = -1;
    while (left<=right) {
        int mid = left+((right-left)>>1);
        if(vec[mid]>value){
            res  = mid;
            right = mid-1;
        }else{
            left = mid+1;
        }
    }
    if(res == -1) return vec.size();
    return res;
}

int main() {
    int n, k;
    cin>>n>>k;

    vector<int> vec(n);
    vector<int> factor2(n+1);
    vector<int> factor5(n+1);

    int totle2 = 0;
    int totle5 = 0;
    for(int i=0;i<n;i++){
        cin>>vec[i];
        int x = factor(vec[i], 2);
        factor2[i+1] = factor2[i]+x;
        totle2+=x;
        x = factor(vec[i], 5);
        factor5[i+1] = factor5[i]+x;
        totle5+=x;
    }
    // 这里进行二分查找加速
    long long ans = 0;
    for(int i=0;i<n;i++){ // 以每个点为起点
        int val2 = totle2+factor2[i]-k;
        int val5 = totle5+factor5[i]-k;
        int pos2 = base_right(factor2, val2);
        int pos5 = base_right(factor5, val5);
        if(min(pos2, pos5)-i-1<=0) continue;
        ans+=min(pos2, pos5)-i-1;
    }
    cout<<ans<<endl;
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/爱喝兽奶帝天荒/article/detail/802311
推荐阅读
相关标签
  

闽ICP备14008679号