• b_lc_使数组和能被 P 整除 & K倍区间(map记录tar_mod的位置 | 公式转换)


    使数组和能被 P 整除

    请你移除 最短 子数组(可以为 空),使得剩余元素的 和 能被 p 整除。 不允许 将整个数组都移除。

    思路
    假设,s为整个数组的和,s%p为k:

    • 如果 k=0,什么都不用移除就,返回0
    • 否则,我们需要找一段子数组 sub,如图
    typedef long long ll;
    class Solution {
    public:
        int minSubarray(vector<int>& A, int p) {
            ll n=A.size(), s=0;
            for (int v : A) s=(s+v)%p;
            ll k=s%p;
            if (k==0) return 0;
            ll cur=0, ans=n+5; 
            unordered_map<ll, ll> m;
            m[0]=-1;
            for (int i=0; i<n; i++) {
                cur+=A[i];
                ll cur_mod=cur%p, tar_mod=(cur_mod-k+p)%p;
                if (m.find(tar_mod)!=m.end()) {
                    ans=min(ans, i-m[tar_mod]);
                }
                m[cur_mod]=i;
            }
            return ans==n ? -1:ans;
        }
    };
    

    K倍区间

    如果其中一段连续的子序列 Ai,Ai+1,…Aj 之和是 K 的倍数,我们就称这个区间 [i,j] 是 K 倍区间。
    求出数列中总共有多少个 K 倍区间.

    思路
    \((s[i]-s[j])%k=0\),则s[i]%k=s[j]%k,我们要找k倍区间就是在找每一种%k前缀和的个数;

    注:在更新每一种前缀和%k的时机是延迟计数,不然会导致计数错误

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=1e6+5;
    ll s[N], m[N];
    
    int main() {
        std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
        ll n,k,x,ans=0; cin>>n>>k;
        for (int i=1; i<=n; i++) cin>>x, s[i]=(s[i-1]+x)%k;
        for (int i=1; i<=n; i++) {
            if (m[s[i]]>0) ans+=m[s[i]];
            m[s[i]]++;
        }
        cout<<ans+m[0];
        return 0;
    }
    
  • 相关阅读:
    设计模式
    操作系统知识点梳理
    jvm面试题
    java排序算法之冒泡排序和快速排序
    使用RAS+AES对接口数据加解密
    MongoDB七-运维技术
    MongoDB三-高级操作
    MongoDB四-操作索引
    quartz详解3:quartz数据库集群-锁机制
    quartz详解4:quartz线程管理
  • 原文地址:https://www.cnblogs.com/wdt1/p/13702575.html
Copyright © 2020-2023  润新知