Namomo Spring Camp 2022 Week1 Day4 选数
Problem Statement
给 N N N个数 a 1 , a 2 , … , a n a_1,a_2,\dots,a_n a1,a2,…,an选出若干个数字, 使得数字的和 m o d N = 0 \mod N=0 modN=0.
输出一个方案.
Solution
首先设 b k = ( ∑ i = 1 k a i ) m o d N b_k=(\sum_{i=1}^ka_i)\mod N bk=(∑i=1kai)modN. b k = { 0 , 1 , 2 , … , N − 1 } b_k=\{0,1,2,\dots,N-1\} bk={0,1,2,…,N−1}.
- 如果 b k = 0 b_k=0 bk=0那么显然有 b k = ( ∑ i = 1 k a i ) m o d N = 0 b_k=(\sum_{i=1}^ka_i)\mod N=0 bk=(∑i=1kai)modN=0即选择 [ 1 , k ] [1,k] [1,k]的所有数即可.
- 否则 ∀ k ∈ [ 1 , N ] , b k ≠ 0 \forall k\in[1,N],b_k\neq0 ∀k∈[1,N],bk=0, 由于 b k ≠ 0 b_k\neq0 bk=0的值域为 { 1 , 2 , … , N − 1 } \{1,2,\dots,N-1\} {1,2,…,N−1}共 N − 1 N-1 N−1个数, 由鸽笼原理 N N N个数 b k b_k bk中至少有 2 2 2个数使得 b l = b r ( l < r ) b_l=b_r(l<r) bl=br(l<r). 那么显然有 b r − b l = ( ∑ i = l + 1 r a i ) m o d N = 0 b_r-b_l=(\sum_{i=l+1}^ra_i)\mod N=0 br−bl=(∑i=l+1rai)modN=0. 则选择 [ l + 1 , r ] [l+1,r] [l+1,r]区间内的所有数即可.
时间复杂度为 O ( N ) O(N) O(N).
Code
# define Fast_IO std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
# include "unordered_map"
# include "algorithm"
# include "iostream"
# include "cstdlib"
# include "cstring"
# include "cstdio"
# include "vector"
# include "bitset"
# include "queue"
# include "cmath"
# include "map"
# include "set"
using namespace std;
const int maxm=1e5+10;
int N,A[maxm],B[maxm];
unordered_map<int,int> LH;
int main(){
static int i,L,R; L=0,R=1;
scanf("%d",&N);
for(i=1;i<=N;i++) scanf("%d",&A[i]),B[i]=(B[i-1]+A[i]%N)%N;
for(i=1;i<=N;i++){
if(LH[B[i]] || B[i]==0){
L=LH[B[i]],R=i;
break;
}else LH[B[i]]=i;
}
printf("%d\n",R-L);
for(i=L+1;i<=R;i++) printf("%d ",i);
return 0;
}
CF557B Modulo Sum
Problem Statement
给你 N N N个数, 选出若干个数使得, 这若干个数的和 m o d M = 0 \mod M=0 modM=0. 判断可不可行.
- 1 ≤ N ≤ 1 0 6 , 2 ≤ M ≤ 1 0 3 1\leq N\leq 10^6,2\leq M\leq10^3 1≤N≤106,2≤M≤103.
Solution
由上题性质可知若 N ≥ M N\geq M N≥M至少存在一种方案, 使得和 m o d M = 0 \mod M=0 modM=0.
如果 N < M N<M N<M:
我们不妨设 f i , j f_{i,j} fi,j表示前 i i i个数是否能达到和在模意义下和为 j j j. A i = a i m o d M A_i=a_i\mod M Ai=aimodM.
显然有 f i , ( j + A i ) mod M = { f i − 1 , j or f i − 1 , ( j + A i ) mod M i f j ≠ 0 t r u e i f j = 0 f_{i,(j+A_i)\text{ mod M}}=\begin{cases}f_{i-1,j}\text{ or }f_{i-1,(j+A_i)\text{ mod }M}&if\;j\neq0\\true&if\;j=0\end{cases} fi,(j+Ai) mod M={fi−1,j or fi−1,(j+Ai) mod Mtrueifj=0ifj=0.
Code
# define Fast_IO std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
# include "unordered_map"
# include "algorithm"
# include "iostream"
# include "cstdlib"
# include "cstring"
# include "cstdio"
# include "vector"
# include "bitset"
# include "queue"
# include "cmath"
# include "map"
# include "set"
using namespace std;
const int maxm=1e6+10;
const int maxn=3e3+10;
int N,M,A[maxm],DP[maxn][maxn],Find;
unordered_map<int,int> LH;
int main(){
static int i,j,Find;
scanf("%d%d",&N,&M);
for(i=1;i<=N;i++) scanf("%d",&A[i]);
if(N>=M){
printf("YES");
return 0;
}
DP[1][A[1]%M]=true;
for(i=2;i<=N;i++){
for(j=0;j<M;j++){
DP[i][(j+A[i])%M]=DP[i-1][j]|DP[i-1][(A[i]+j)%M];
}DP[i][A[i]%M]=true;
}puts(DP[N][0]?"YES":"NO");
return 0;
}
Link
Link1: Daimayuan Online Judge 456 选数
Link2: CF577B Modulo Sum