1. 程式人生 > 實用技巧 >b_51_N的倍數(抽屜原理+字首和)

b_51_N的倍數(抽屜原理+字首和)

一個長度為N的陣列A,從A中選出若干個數,使得這些數的和是N的倍數。
2<=N<=50000;0<A[i]<=10^9

思路:A[i]對N取模的結果為1~N-1(共N-1個數),而A有N個數,這就說明這些模N的數中至少有兩個數是一樣的(抽屜原理保證了資料一定有解);然後就是分兩種情況:

  • 字首和s[0:i]中有0出現,則輸出A[0~i]
  • 否則,如果存在兩個字首s[i]和s[j](i!=j)和它們的值相等,則證明s[j...i]這一段一定是n的倍數(模n為0)

這裡咬注意啊:下標從0開始的話如果第一個數就是n的倍數,需要特判一下,因為這句:cout<<i-j<<'\n';

#include<bits/stdc++.h>
#define rep1(i,s,e) for( int i=s;i<=e;i++)
#define rep2(i,s,e) for( int i=e;i>=s;i--)
using namespace std;
typedef long long ll;
const int N=5e5+5;
ll n,s,a[N],mp[N];
int main() {
    std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    cin>>n; rep1(i,1,n) cin>>a[i];
    //mp[0]=0;
    rep1(i,1,n) {
        s=(s+a[i])%n;
        if (s==0 || mp[s]) {
            int j=mp[s];
            cout<<i-j<<'\n'; 
            rep1(k,j+1,i) cout<<a[k]<<'\n';
            break;
        } else {
            mp[s]=i;
        }
    }
    return 0;
}