CF 577 B. Modulo Sum 鴿巢原理/01揹包 (*1800)

Showball發表於2024-10-09

CF 577 B. Modulo Sum 鴿巢原理/01揹包

題目連結

思路

每個數可選可不選,經典的01揹包問題,但是資料範圍過大,因為要找可行解即可,考慮去找滿足題意的子陣列(子陣列是特殊的子序列)。就變成一個經典的字首和問題。只需要找到字首和陣列中存在兩個相等的值,那麼滿足條件。由於需要取模,那麼字首和結果只有 \([0,m)\)\(m\) 種情況。那麼根據 鴿巢原理 顯然當 \(n>m\) 時,一定有解。這樣我們只需要考慮 \(n\le m\) 的情況,資料範圍就縮小了,01揹包處理即可。

#include<bits/stdc++.h>

using namespace std;

using i64=long long;

void Showball(){
    int n,m;
    cin>>n>>m;
    vector<int> a(n+1);
    for(int i=1;i<=n;i++){
        cin>>a[i];
        a[i]%=m;
    } 
    if(n>m) return cout<<"YES\n",void();
    vector<vector<int>> dp(n+1,vector<int>(m+1));
    
    bool ok=false;
    for(int i=1;i<=n;i++){
        dp[i][a[i]]=1;
        for(int j=1;j<=m;j++){
            dp[i][j]|=dp[i-1][j];
            dp[i][(j+a[i])%m]|=dp[i-1][j];
        }
        ok|=dp[i][0];
    }
    cout<<(ok?"YES\n":"NO\n");
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t=1;
    //cin>>t;

    while(t--){
      Showball();
    }

    return 0;
}

相關文章