zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    colock
    ToggleButton 和 Switch
    radioButon的使用
    kotlin中val和var的区别
    textEdit
    c++ 网络编程基础
    网格布局 GridLayout
    数组、指针和引用
    Hello Word
    Win7-U盘安装出现"We were unable to copy your files. "
  • 原文地址:https://www.cnblogs.com/wdt1/p/13702575.html
Copyright © 2011-2022 走看看