飘花效果

2022 绍兴市小学组 3.美感(beautiful)

题目

首先将 \(\forall a_i\gets a_i\bmod m\)

题目要求求“最少删除多少个数”,那么我们可以转换一下成:“最多保留多少个数”。

考虑 \(\mathcal O(n^2)\) 做法,设 \(f_i\) 表示以 \(i\) 为序列最后一个能够保留数的最多数量,则有 \(f_i = \max\limits_{j=1}^{i-1} [\left(a_i+a_j\right)\bmod m = 0]f_j + 1\),最终答案为 \(n - \left(\max\limits_{i=1}^n f_i\right)\),注意判断最优答案是长度为 \(1\) 的情况。

初始 \(\forall f_i = 1\)

这样有 \(90\texttt{pts}\)

# include <bits/stdc++.h>

# define int long long
# define rint register int
# define ME ; 
# define AK 0
# define SX2022 return

inline int read();
inline void write(int x);
inline void writesp(int x);
inline void wrietln(int x);

//---------------------------------

using namespace std;

const int N = 1e5 + 10;
int n ,m ,ans ,a[N] ,f[N];

inline void fre(){
  freopen("beautiful.in" ,"r" ,stdin);
  freopen("beautiful.out" ,"w" ,stdout);
} 

signed main(){
  n = read() ,m = read();
  for(rint i = 1 ;i <= n; i ++)
    a[i] = read() ,a[i] %= m;
  f[1] = ans = 1;
  for(rint i = 2 ; i <= n ;i ++){
  	for(rint j = 1; j < i ;j ++)
  	  if((a[i] + a[j]) % m == 0) f[i] = max(f[i] ,f[j] + 1);
  	ans = max(ans ,f[i]);
  } 
  if(n <= 5000) printf("%lld\n" ,n - ans);
  else printf("%lld\n" ,n - 1);
  SX2022 AK ME
}


inline int read(){
  int s = 0 ,w = 0;
  char c = getchar();
  while(!isdigit(c)){
  	w |= (c == '-');
	c = getchar();
  } while(isdigit(c)){
  	s = (s << 1ll) + (s << 3ll) + (c ^ 48);
  	c = getchar();
  } return w ? -s : s;
} inline void write(int x){
  if(x < 0) putchar('-') ,x = -x;
  if(x >= 10) write(x / 10);
  putchar (x % 10 | 48);
} inline void writesp(int x){
  write(x) ,putchar(' ');
} inline void writeln(int x){
  write(x) ,putchar('\n');
} 

引理:\((k_1 + k_2) \bmod m = (k_1\bmod m + k_2\bmod m)\bmod m\)

如果这个数可以保存,当且仅当有一个 \(j\)\(1\le j < i\)) 满足 \((a_i + a_j)\bmod m = 0\),逆推得出合适的一个 \(a_j = m - a_i\)

\(f_i\) 表示以 \(i\) 为余数,并且为序列最后一个数的最多保留数量,则有 \(f_{a_i} = \max\left(f_{a_i} ,f_{m - a_i} + 1\right)\)

最后的答案即为 \(\max\limits_{i=0}^m f_i\)

# include <bits/stdc++.h>

# define int long long
# define rint register int
# define ME ; 
# define AK 0
# define SX2022 return

inline int read();
inline void write(int x);
inline void writesp(int x);
inline void wrietln(int x);

//---------------------------------

using namespace std;

const int N = 1e5 + 10;
int n ,m ,ans ,ans1 ,ans2 ,b[N] ,a[N] ,f[N];

inline void fre(){
  freopen("beautiful.in" ,"r" ,stdin);
  freopen("beautiful.out" ,"w" ,stdout);
} signed main(){
  n = read() ,m = read();
  for(rint i = 1 ;i <= n; i ++)
    a[i] = read() ,a[i] %= m;
  for(rint i = 1 ; i <= n ;i ++){
  	int aj = m - a[i];
  	if(aj == m) aj = 0;
	f[a[i]] = max(f[a[i]] ,f[aj] + 1);
  } for(rint i = 0 ; i < m; i ++) ans = max(ans ,f[i]);
  printf("%lld\n" ,n - ans);
  SX2022 AK ME
}






inline int read(){
  int s = 0 ,w = 0;
  char c = getchar();
  while(!isdigit(c)){
  	w |= (c == '-');
	c = getchar();
  } while(isdigit(c)){
  	s = (s << 1ll) + (s << 3ll) + (c ^ 48);
  	c = getchar();
  } return w ? -s : s;
} inline void write(int x){
  if(x < 0) putchar('-') ,x = -x;
  if(x >= 10) write(x / 10);
  putchar (x % 10 | 48);
} inline void writesp(int x){
  write(x) ,putchar(' ');
} inline void writeln(int x){
  write(x) ,putchar('\n');
} 
posted @ 2024-08-27 12:37  2021zjhs005  阅读(15)  评论(0)    收藏  举报