Dãy con dài nhất có tổng chia hết cho k

Cho một hàng gồm n (1 1, A2, …, An và số nguyên ổn dương k (k Dòng 1: Chẹn số nDòng 2: Chứa hẹn n số A1, A2, …, An cách nhau tối thiểu một vệt cách
Dòng 1: Ghi độ lâu năm hàng con tìm đượcCác cái tiếp: Ghi những phần tử được lựa chọn vào hàng conDòng cuối: Ghi tổng các bộ phận của hàng bé kia.

You watching: Dãy con dài nhất có tổng chia hết cho k

SUBSEQ.INP

SUBSEQ.OUT

10 5

8

1 6 11 5 10 15 trăng tròn 2 4 9

a<10> = 9

a<9> = 4

a<7> = 20

a<6> = 15

a<5> = 10

a<4> = 5

a<3> = 11

a<2> = 6

Sum = 80

3.4.1. Cách giải 1

Đề bài xích thưởng thức chọn ra một số tối đa các phần tử trong dãy A và để được một hàng bao gồm tổng phân chia hết mang đến k, ta rất có thể giải bài xích toán thù bằng cách thức coi ngó tổ hợp bởi xoay lui gồm nhận xét nhánh cận nhằm giảm bớt ngân sách vào nghệ thuật vét cạn. Dưới đây ta trình bày cách thức quy hoạch động:

Nhận xét 1: Không tác động mang lại kết quả ở đầu cuối, ta rất có thể đặt: Ai := Ai mod k với tất cả i: 1 i1, Ai2, …, Aim. Các phần tử này có tổng đồng dư với S theo mô-đun k.

Xét các dãy sau:

Dãy 0 := () = Dãy rỗng (Tổng = 0 (thủ thuật k))

Dãy 1 := (Ai1) Dãy 2 := (Ai1, Ai2)

Dãy 3 := (Ai1, Ai2, Ai3)

… …

Dãy m := (Ai1, Ai2, …, Aim)

bởi thế có m + 1 hàng, giả dụ m >= k thì theo nguyên lý Dirichlet vẫn sống thọ nhì dãy có tổng đồng dư theo mô-đun k. Giả sử đó là nhì dãy:

Ai1 + Ai2 + … + Aip = Ai1 + Ai2 + … + Aip + Aip+1 + … + Aiq (gian lận k)

Suy ra Aip+1 + … + Aiq phân chia hết mang lại k. Vậy ta rất có thể xoá không còn các thành phần này vào hàng vẫn chọn mà vẫn được một dãy có tổng đồng dư với S theo modul k, mâu thuẫn cùng với giả thiết là hàng đang lựa chọn có số bộ phận buổi tối tgọi.


Công thức truy vấn hồi:

Nếu ta Hotline F là số phần tử tối tgọi buộc phải chọn vào dãy A1, A2, …, Ai để sở hữu tổng phân chia k dư t. Nếu không tồn tại phương pháp lựa chọn ta coi F =

*
. Khi đó F được tính qua công thức tầm nã hồi sau:

Nếu vào dãy bên trên chưa phải lựa chọn Ai thì F = F;

Nếu trong dãy bên trên bắt buộc lựa chọn Ai thì F = 1 + F*

> (
*
ngơi nghỉ đâyđọc là phxay trừ trên các lớp đồng dư mod k. lấy một ví dụ Lúc k = 7 thì
*
= 5).

See more: Jebrains Resharper 2021 - Jebrains Resharper Ultimate

Từ trên suy ra F = min (F, 1 + F).

Còn tất nhiên, cơ sở quy hoạch động: F(0, 0) = 0; F(0, i) =

*
(cùng với "i: 1 const InputFile = 'SUBSEQ.INP'; OutputFile = 'SUBSEQ.OUT'; maxN = 1000; maxK = 50;var a: array<1..maxN> of Integer; f: array<0..maxN, 0..maxK - 1> of Byte; n, k: Integer;procedure Enter;var fi: Text; i: Integer;begin Assign(fi, InputFile); Reset(fi); ReadLn(fi, n, k); for i := 1 khổng lồ n vì chưng Read(fi, a); Close(fi);end;function Sub(x, y: Integer): Integer; Tính x - y (theo gian lận k)var tmp: Integer;begin tmp := (x - y) thủ thuật k; if tmp >= 0 then Sub := tmp else Sub := tmp + k;end;procedure Optimize;var i, t: Integer;begin FillChar(f, SizeOf(f), $FF); Khởi tạo thành những thành phần f<0, .> đều bởi 255 () f<0, 0> := 0; Ngoại trừ f<0, 0> := 0 for i := 1 khổng lồ n vày for t := 0 khổng lồ k - 1 bởi Tính f := min (f, f + 1 if f f)> + 1 then f := f else f := f)> + 1;end;procedure Result;var fo: Text; i, t: Integer; SumAll, Sum: LongInt;begin SumAll := 0; for i := 1 to n bởi SumAll := SumAll + a; Assign(fo, OutputFile); Rewrite(fo); WriteLn(fo, n - f); n - số phần tử bỏ đi = số thành phần giữ lại i := n; t := SumAll thủ thuật k; Sum := 0; for i := n downto 1 vì chưng if f = f then Nếu cách thực hiện về tối ưu ko bỏ ai, tức là bao gồm lựa chọn ai begin WriteLn(fo, 'a<', i, '> = ', a); Sum := Sum + a; over else t := Sub(t, a); WriteLn(fo, 'Sum = ', Sum); Close(fo);end;begin Enter; Optimize; Result;over.

3.4.2. Cách giải 2

Phân các thành phần vào dãy a theo những lớp đồng dư modul k. Lớp i có những phần tử phân chia k dư i. call Count là số lượng các thành phần trực thuộc lớp i.

See more: Khắc Phục Mất Sóng Điện Thoại Trong Nhà Không Có Sóng Điện Thoại, Cách Khắc Phục

Với 0 = 1; 0 const InputFile = 'SUBSEQ.INP'; OutputFile = 'SUBSEQ.OUT'; maxN = 1000; maxK = 50;var a: array<1..maxN> of Integer; Count: array<0..maxK - 1> of Integer; f, Trace: array<0..maxK - 1, 0..maxK - 1> of Integer; n, k: Integer;procedure Enter;var fi: Text; i: Integer;begin Assign(fi, InputFile); Reset(fi); ReadLn(fi, n, k); FillChar(Count, SizeOf(Count), 0); for i := 1 to lớn n vì chưng begin Read(fi, a); Inc(Count thủ thuật k>); Nhập tài liệu đồng thời với bài toán tính những Count<.> end; Close(fi);end;function Sub(x, y: Integer): Integer;var tmp: Integer;begin tmp := (x - y) gian lận k; if tmp >= 0 then Sub := tmp else Sub := tmp + k;end;procedure Optimize;var i, j, t: Integer;begin FillChar(f, SizeOf(f), 0); f<0, 0> := Count<0>; FillChar(Trace, SizeOf(Trace), $FF); Khởi tạo thành các mảng Trace=-1 Trace<0, 0> := Count<0>; Ngoại trừ Trace<0, 0> = Count<0> for i := 1 to k - 1 vị for t := 0 to k - 1 bởi for j := 0 khổng lồ Count vì if (Trace -1) and (f f + j) then begin f := f + j; Trace := j; end;end;procedure Result;var fo: Text; i, t, j: Integer; Sum: LongInt;begin t := 0; Tính lại những Count := Số phần tử phương án tối ưu đã chọn vào lớp i for i := k - 1 downkhổng lồ 0 vì chưng begin j := Trace; t := Sub(t, j * i); Count := j; end; Assign(fo, OutputFile); Rewrite(fo); WriteLn(fo, f); Sum := 0; for i := 1 lớn n vày begin t := a hack k; if Count > 0 then begin WriteLn(fo, 'a<', i, '> = ', a); Dec(Count); Sum := Sum + a; end; end; WriteLn(fo, 'Sum = ', Sum); Close(fo);end;begin Enter; Optimize; Result;over.Cách giải vật dụng hai xuất sắc hơn biện pháp giải thứ nhất vì nó có thể triển khai với n béo. lấy một ví dụ này cho thấy một bài xích toán thù quy hoạch rượu cồn có thể có rất nhiều phương pháp đặt cách làm tróc nã hồi để giải.


Chuyên mục: Chia sẻ