1. Trang chủ
  2. » Công Nghệ Thông Tin

Cách sáng tạo trong lập trình

72 453 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Cách sáng tạo trong lập trình
Trường học Đại học Khoa học Tự nhiên, Đại học Quốc gia Hà Nội
Chuyên ngành Computer Science
Thể loại Bài luận
Năm xuất bản 2010
Thành phố Hà Nội
Định dạng
Số trang 72
Dung lượng 521,26 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

sáng tạo trong lập trình - Nhưng sáng tạo hay dành cho dân lập trình hay

Trang 1

Thi HSG Quốc gia 2010

CCKLK: Dãy con chung không liền kề dài nhất

Cho dãy số nguyên dương x = (x 1 , x 2 , , x n ) Dãy y = (x i1 , x i2 , , x ik ) được gọi là dãy con không liền kề của dãy x nếu 1  i1 < i21 < < ik1  n Cho 2 dãy số nguyên a gồm n phần tử và b gồm m phần tử Xác định chiều dài k của dãy con chung không liền kề dài nhất của a và b 2  m, n  1000, 1 ai, bi  10000

CCKLK.INP CCKLK.OUT Giải thích

Gọi d(i,j) là đáp số của bài toán khi xét hai dãy a[1 i] và b[1 j] Ta có:

 Nếu i ≤ 0 thì ta quy ước d(i,j) = 0,

 Nếu a[i] = b[j] thì d(i,j) = d(i−2,j−2),

 Nếu a[i] ≠ b[j] thì d(i,j) = max { d(i−1,j), d(i,j−1) }

Để cài đặt ta dùng 3 mảng một chiều x, y và z với ý nghĩa x[j] = d(i−2,j), y[j] = d(i−1,j) và z[j] = d(i,j) Khi

đó hệ thức trên được viết là:

 Nếu i ≤ 0 thì ta quy ước d(i,j) = 0,

 Nếu a[i] = b[j] thì d(i,j) = d(i−2,j−2) ứng với z[j] = x[j−2],

 Nếu a[i] ≠ b[j] thì d(i,j) = max { d(i−1,j), d(i,j−1) } ứng với z[j] = max { y[j], z[j−1] }

Muốn tránh các phép copy dữ liệu từ y sang x; từ z sang y và từ x sang z ta chỉ cần tráo đổi các con trỏ mảng

Độ phức tạp

O(n.m)

Chương trình Pascal

(* CCKLK.PAS

k: chieu dai day con chung khong lien ke dai nhat

cua hai day so nguyen duong a[1 n], b[1 m]

*)

const fn = 'ccklk.inp'; gn = 'ccklk.out';

bl = #32; nl = #13#10; mn = 1001;

type int = integer;

mi1 = array[0 mn] of int;

var

n, m: int;

a, b: mi1;

function Max(a,b: int): int;

begin if a >= b then Max := a else Max := b; end;

Trang 3

const char * fn = "ccklk.inp";

const char * gn = "ccklk.out";

for (i = 1; i <= n; ++i) f >> a[i];

for (i = 1; i <= m; ++i) f >> b[i];

cout << endl << "a: ";

for (i = 1; i <= n; ++i) cout << a[i] << " "; cout << endl << "b: ";

for (i = 1; i <= m; ++i) cout << b[i] << " "; f.close();

Trang 4

2 ONDINH.INP: Dòng đầu: n m s Từ dòng thứ hai trở đi:m cung

dạng u v Có thể có các cung trùng nhau (dư thừa)

Trang 5

int len[mn]; // len[i] chieu dai s => i

char mark[mn]; // mark[i] danh dau dinh i:

// Chua xet 0; Co trong hang doi q 1; Da xu li 2

int d[mn]; // d[i] so luong duong ngan nhat s => i

int q[mn]; // hang doi

int n, m, s ; // so dinh n, so cung m, dinh xuat phat s // P R O T O T Y P E S

int main();

void Doc();

int XuLi();

int Min(int, int);

int BinSearch(cung [], int, int, int);

int Sanh(int,int,int,int);

void Ghi();

int main(){

Doc(); XuLi(); Ghi();

cout << endl << " Fini"; cin.get();

Trang 6

j = c[k].b; // xet cac dinh j ke dinh i

int Sanh(int u1, int v1, int u2, int v2) {

if (u1 < u2) return -1;

if (u1 > u2) return 1;

Trang 7

int Min(int, int);

int BinSearch(cung [], int, int, int);

int Sanh(int,int,int,int);

void Ghi();

int main(){

Doc(); XuLi(); Ghi();

cout << endl << " Fini"; cin.get();

Trang 8

int Sanh(int u1, int v1, int u2, int v2) {

if (u1 < u2) return -1;

if (u1 > u2) return 1;

Trang 9

m = k;

}

Mã số thuế

Xét tập S gồm tất cả các số 1 n trong hệ 36, 36  n  10 16 Cho số m: 3  m  70 Xét dãy số nguyên 1 < c 1

< c 2 < < c k < 36, k = (m1)/2 , x là số nguyên lớn nhất không vượt quá x

Chọn các số chứa các chữ số < c1 cấp cho 2 nhóm 1 và 2 rồi xóa các số này Chọn các số chứa các chữ số

< c2 cấp cho 2 nhóm 3, 4 Các số còn lại cấp cho 1 hoặc 2 nhóm cuối

1  n, a i  100000

Dữ liệu vào: Tệp văn bản diff.inp

Dòng đầu tiên: số n

Từ dòng thứ hai trở đi: dãy số a

Dữ liệu ra: Tệp văn bản diff.out chứa 2 số:

imax  chỉ số đầu tiên của đoạn dài nhất tìm được trong dãy a

dmax  số phần tử của doạn dài nhất

Các số trên cùng dòng cách nhau qua dấu cách

diff.inp diff.out Giải thích

Lần lượt đọc các phần tử ai của dãy a và đánh dấu vị trí xuất hiện của ai trong dãy thông qua mảng p, p[ai] =

i Với thí dụ đã cho, sau khi đọc và xử lý xong dãy a ta phải thu được

Trang 10

p[2] = 2/7 cho biết số 2 lúc đầu xuất hiện tại vị trí 2 trong dãy a, sau đó xuất hiện tại vị trí 7 trong dãy a p[8] = p[10] = 0 cho biết các số 8 và 10 không xuất hiện trong dãy a

Ta gọi p là dãy trỏ ngược hay dãy vị trí của dãy a Ta xử lý từng đoạn d của ai như sau Mỗi đoạn d sẽ bao gồm một dãy liên tiếp các phần tử đôi một khác nhau tính từ chỉ số i đến j Thí dụ trên cho ta lần lượt 3 đoạn sau:

 Đoạn thứ nhất d = a[1 4] = (5, 2, 4, 1), i = 1, j = 4,

 Đoạn thứ hai d = a[2 6] = (2, 4, 1, 5, 3), i = 2, j = 6,

 Đoạn thứ ba d = a[3 10] = (4, 1, 5, 3, 2, 7, 6, 9), i = 3, j = 10

Mỗi đoạn d được xác định như sau: Mỗi khi gặp phần tử aj đầu tiên trùng với một phần tử trong dãy tính từ

i thì ta cắt ra được đoạn d = a[i j1]

Với mỗi đoạn d[i j] ta tính số phần tử của đoạn đó là ji+1 và cập nhật giá trị dmax Để khởi trị cho đoạn tiếp theo, ta đặt i = p[aj]+1 Chú ý rằng p[aj] là vị trí xuất hiện của giá trị lặp aj

Độ phức tạp

O(n)

Chương trình Pascal

(* diff.pas

Tim doan dai nhat gom cac

phan tu doi mot khac nhau

imax, dmax: longint;

{ imax - chi so dau tien cua doan dai nhat

dmax - so phan tu cua doan dai nhat }

Trang 11

Tim doan dai nhat gom cac

phan tu doi mot khac nhau

const char * fn = "diff.inp";

const char * gn = "diff.out";

const int mn = 100001;

int p[mn]; // p[v] = i: noi xuat hien so v trong day int n;

int imax; // chi so dau tien cua doan dai nhat

int dmax; // so phan tu cua doan dai nhat

Trang 12

Từ dòng thứ hai trở đi: dãy số a

Dữ liệu ra: Tệp văn bản hv1k.out chứa 2 số:

imax  chỉ số đầu tiên của đoạn dài nhất tìm được trong dãy a

dmax  số phần tử của đoạn dài nhất

Các số trên cùng dòng cách nhau qua dấu cách

hv1k.inp hv1k.out Giải thích

4 1 5 3 2 6

Thuật toán

Kí hiệu a[i j] là đoạn gồm các phần tử liên tiếp từ ai đến aj của dãy a và kí hiệu set(x) là tập chứa các phần

tử (khác nhau) của dãy x Với thí dụ đã cho ta có, a[1 5] = (5, 2, 4, 1, 5) và do đó set(a[1 5]) = {1, 2, 4, 5} Gọi p là dãy vị trí (trỏ ngược) của dãy a Vì dãy a gồm các phần tử đôi một khác nhau nên p cũng chứa các chỉ số đôi một khác nhau Khi đó a chứa một đoạn là hoán vị của k số tự nhiên đầu tiên (1,2, ,k) khi và chỉ khi tìm được hai chỉ số s và e thỏa đồng thời hai tính chất sau:

 es+1 = k, và

 set(a[s e]) = {1, 2, , k}

Trang 13

Trong thí dụ trên ta tìm được s = 3, e = 8, k = 6, a[3 8] = (4, 1, 5, 3, 2, 6), và do đó set(a[3 8]) = {1, 2, 3, 4,

5, 6}

Xét dãy chỉ số 1, 2, , i thỏa tính chất  j: 1  j  i: p[j] ≠ 0

Để ý rằng điều kiện p[j] ≠ 0 tương đương với điều kiện giá trị j của dãy a xuất hiện tại vị trí p[j] Đặt s = min p[1 i] = min {p[1], p[2], , p[i]} và e = max p[1 i] = max {p[1], p[2], , p[i]} Ta thấy a chứa một đoạn là hoán vị của dãy (1,2, ,i) khi và chỉ khi es+1 = i

Tim doan dai nhat trong day so

doi mot khac nhau tao thanh mot

Trang 14

Tim doan dai nhat trong day so

doi mot khac nhau tao thanh mot

const char * fn = "hv1k.inp";

const char * gn = "hv1k.out";

int Min(int, int);

int Max(int, int);

void Hv();

void Ghi();

Trang 15

int Min(int a, int b) { return (a <= b) ? a : b; }

int Max(int a, int b) { return (a >= b) ? a : b; }

Trang 16

Dữ liệu vào: Tệp văn bản hvsk.inp

Dòng đầu tiên: số n

Từ dòng thứ hai trở đi: dãy số a

Dữ liệu ra: Tệp văn bản hvsk.out chứa 2 số:

imax  chỉ số đầu tiên của đoạn dài nhất tìm được trong dãy a

dmax  số phần tử của đoạn dài nhất

Các số trên cùng dòng cách nhau qua dấu cách

hvsk.inp hvsk.out Giải thích

Khi duyệt p[vmin vmax] ta xét 2 trạng thái 0 và 1 như sau:

Trạng thái 0: Duyệt đoạn p toàn 0, p[2 3] và p[9 11]

Nếu gặp p[i] > 0 thì khởi trị cho trạng thái duyệt đoạn khác 0, p[istart ]:

Ghi nhận chỉ số đầu đoạn khác 0: istart = i,

Khởi trị cac giá trị pmin = min p[istart k1] và pmax = max p[istart k1] cho đoạn này: pmin =

pmax = p[i],

 Chuyển qua trạng thái 1

Trạng thái 1: Duyệt đoạn p khác 0, p[1 1], p[4 8] và p[12 12]

Nếu p[i] > 0 thì cập nhật các chỉ số pmin và pmax Kiểm tra đẳng thức pmaxpmin = iistart để cập nhật chỉ số đầu tiên của đoạn hoán vị trong dãy a, imax và chiều dài của đoạn hoán vị, dmax

Nếu p[i] = 0 thì kết thúc việc duyệt đoạn p[isstart i1] này, chuyển qua trạng thái 0

Độ phức tạp

O(n)

Trang 17

Chương trình Pascal

Chương trình CPP

/* - hvsk.cpp

Tim doan dai nhat trong day so

doi mot khac nhau tao thanh mot

hoan vi cua day so tu nhien lien tiep

const char * fn = "hvsk.inp";

const char * gn = "hvsk.out";

const int mn = 100002;

int p[mn];

int pmin, pmax;

int vmin, vmax;

int Min(int, int);

int Max(int, int);

void Hv(); // Sliding window

Trang 18

}

f.close();

}

int Min(int a, int b) { return (a <= b) ? a : b; }

int Max(int a, int b) { return (a >= b) ? a : b; }

case 0: // duyet doan toan 0

if (p[i] > 0) { // Khoi tri khi gap so khac 0

pmin = pmax = p[i];

số tự nhiên 1 k; 1  n, a i  100000

Dữ liệu vào: Tệp văn bản hv1kmax.inp

Dòng đầu tiên: số n

Trang 19

Từ dòng thứ hai trở đi: dãy số a

Dữ liệu ra: Tệp văn bản hv1kmax.out chứa 2 số:

imax  chỉ số đầu tiên của đoạn dài nhất tìm được trong dãy a

dmax  số phần tử của đoạn dài nhất

Các số trên cùng dòng cách nhau qua dấu cách

hv1kmax.inp hv1kmax.out Giải thích

(* hv1kmax.pas: Tim doan dai nhat gom cac

phan tu tao thanh mot hoan vi cua 1 k *)

const fn = 'hv1kmax.inp'; gn = 'hv1kmax.out';

mn = 100002; bl = #32; nl = #13#10;

var p: array[0 mn] of longint;

{ p[v] - noi xuat hien gia tri v trong day }

n: longint;

imax, dmax: longint;

f, g: text;

function Min(a,b: longint): longint;

begin if (a <= b) then Min := a else Min := b; end;

function Max(a,b: longint): longint;

begin if (a >= b) then Max := a else Max := b; end;

Trang 20

read(f,v); { v – phan tu dau day a }

p[v] := 1; istart := 1; { chi so dau doan }

if (i-istart > dmax) then Hv(istart, i-1);

istart := p[v]+1; { Khoi tri dau doan moi }

Tim doan dai nhat gom cac

phan tu tao thanh mot hoan vi cua 1 k

Trang 21

const char * fn = "hv1kmax.inp";

const char * gn = "hv1kmax.out";

int Min(int, int);

int Max(int, int);

void Hv(int, int); // Sliding window

// gom cac phan tu khac nhau doi mot

void Hv(int d, int c) {

int i, pmin = c+1, pmax = d-1;

Trang 22

Cho dãy a gồm n số nguyên dương Hãy tìm đoạn dài nhất gồm các phần tử tạo thành một hoán vị của dãy

số nguyên dương liên tiếp s, s+1, ,k; 1  n, a i  100000

Dữ liệu vào: Tệp văn bản hvskmax.inp

Dòng đầu tiên: số n

Từ dòng thứ hai trở đi: dãy số a

Dữ liệu ra: Tệp văn bản hvskmax.out chứa 2 số:

imax  chỉ số đầu tiên của đoạn dài nhất tìm được trong dãy a

dmax  số phần tử của đoạn dài nhất

Các số trên cùng dòng cách nhau qua dấu cách

hvskmax.inp hvskmax.out Giải thích

Pha 2 Duỵệt dãy giá trị i = vmin vmax tạo thành một đoạn d gồm các giá trị xuất hiện liên tiếp trong dãy

a, xác định các giá trị pmin và pmax là vị trí xuất hiện đầu tiên và cuối cùng trong đoạn d Đoạn d là một

hoán vị của dãy số nguyên dương liên tiếp i, i+1, ,s khi và chỉ khi pmaxpmin+1 = si

Độ phức tạp

Chương trình Pascal

Chương trình CPP

/* DevC++: hv1kmax.cpp

Tim doan dai nhat gom cac

phan tu tao thanh mot hoan vi cua s k

*/

Trang 23

#include <fstream>

#include <iostream>

using namespace std;

// D A T A A N D V A R I A B L E S

const char * fn = "hvskmax.inp";

const char * gn = "hvskmax.out";

int Min(int, int);

int Max(int, int);

void Hv(int, int); // Sliding window

int Min(int a, int b) { return (a <= b) ? a : b; }

int Max(int a, int b) { return (a >= b) ? a : b; }

void Hv(int d, int c) {

int i, istart, q = 0, pmin = c+1, pmax = d-1;

int vmin, vmax;

case 0: // duyet doan toan 0

if (p[i] > 0) { // Khoi tri khi gap so khac 0 pmin = pmax = p[i];

Trang 25

char p[mn]; // p[i] = 0=> i nguyen to

Trang 26

Cho n số tự nhiên ai i = 1 n Hãy tìm đoạn dài nhất gồm các phần tử, trong đó hai phần tử kề nhau thì nguyên tố cùng nhau

const char * fn = "coprime.inp";

char p[mn]; // p[i] = 0=> i nguyen to

Trang 27

Bài toán Euler N 28

Trong ma trận vuông n X n, n lẻ xuất phát từ ô giữa ghi lần lượt các số từ 1 n2 theo đường xoắn ốc theo chiều kim dồng hồ Với n = 5 tổng các phần tử trên 2 đường chéo là 101 Hãy tính tổng này với n = 1001

Trang 28

cout << endl << Euler28(1001); // 669171001

cout << endl << " Fini";

cin.get();return 0 ;

}

Bài toán Euler N 52

Số x = 125874, và 2x = 251748 được tạo bởi cùng chữ số theo trật tự khác nhau Tìm số tự nhiên nhỏ nhất

x sao cho 2x, 3x, 4x, 5x và 6x có các chữ số ddoooi một khác nhau và là những hoán vị của x (142857)

Có trên 5 số thỏa tính chất trên hay ko?

Nếu ko đòi hỏi các chữ số khác nhau?

Với các số nguyên dương 1 4294967295 (232 − 1) có 10 số

Trang 29

void GetDigits(UI x, char dg[]) {

for (int i = 0; i < 10; ++i) dg[i] = 0;

for (int i = 0; i < 10; ++i)

if (digits[i] != mark[i]) return false; return true;

for (int i = 2; i <= 6; ++i, x += d) {

if (!SameDigits(x)) return false;

f << endl << d << " : " << x;

Trang 30

Tìm được 340059 số, số cuối là 4870843 với lặp n < 500

Ý tưởng: nếu p[1 n] , c = p[n] là danh sách n số nguyên tố đầu tiên và x là một số lẻ trong khoảng c c*c thì

x là nguyên tố khi và chỉ khi x không có ước nguyên tố trong khoảng 3 x

Xuất phát p = (2,3) − 2 số nguyên tố đầu tiên n = 2 là số lượng các số nguyên tố hiện tìm được

Find: xét các số lẻ x trong khoảng từ pn + 2 đến pn − 2 Chú ý, do pn là số lẻ nên pn lẻ Nếu x là ng tố thì thêm vào dãy

Để kiểm tra tính ng tố của x

for (UI i = 2; p[i] <= can; ++i)

if (x % p[i] == 0) return false;

return true;

}

Trang 31

If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and

9 The sum of these multiples is 23

Find the sum of all the multiples of 3 or 5 below 1000

we get 3, 5, 6 and 9 The sum of these multiples is 23

Find the sum of all the multiples of 3 or 5 below 1000

*/

#include <iostream>

#include <stdio.h>

const int mn = 1001;

Trang 32

while (a[n] < maxval) {

while (3*a[i3] <= a[n]) ++i3;

cout << endl << Euler01(1000); // 3822

cout << endl << " Fini";

cin.get();

return 0 ;

}

Each new term in the Fibonacci sequence is generated by adding the previous two terms

By starting with 1 and 2, the first 10 terms will be:

Trang 33

fi+2 = fi + fi+1 = fi + fi−1 + fi = 2fi + fi−1 (lẻ),

fi+3 = f i+1 + fi+2 = fi−1 + fi + 2fi + fi−1 = 3fi + 2fi−1 = 2fi+2 − fi (chẵn)

Ta sử dụng biến odd để lưu số lẻ và biến even lưu số chẵn sát sau odd Ta có,

Khởi trị: odd = 1; even = 2;

Bước tiếp theo: odd = 2*even + odd; even = 2*odd – even;

1, 2, 3, 5, 8, 13, 21, 34, 55, 89,

Find the sum of all the even-valued terms in the sequence

which do not exceed four million

*/

#include <iostream>

#include <stdio.h>

using namespace std;

int Euler02(int maxval) {

int odd = 1, even = 2;

int s = even;

while (even < maxval) {

odd = 2*even + odd;

even = 2*odd - even;

cout << endl << Euler02(4000000); // 4613732

cout << endl << " Fini";

cin.get();

return 0 ;

}

Trang 34

Euler03

The prime factors of 13195 are 5, 7, 13 and 29

What is the largest prime factor of the number 600851475143 ?

Khởi trị với danh sách chứa k = 2 số nguyên tố p[1] = 2; p[2] = 3 Hàm NextPrime(k) tìm số nguyên tố sát sau sô nguyên tố p[k] Gọi hàm NextPrime nhiều lần đến khi thu được số nguyên tố p[k] > n DuThe prime factors of 13195 are 5, 7, 13 and 29

What is the largest prime factor of the number 600851475143 ? (6857)

The prime factors of 13195 are 5, 7, 13 and 29

What is the largest prime factor of the number

for (int i = 1; p[i] <= ys; ++i)

if (fmodl(y,p[i]) == 0.0) return false;

return true;

}

Trang 35

// Given a list consequenced first k prime numbers // p[1 k] = (3,5,7, p[k]), k > 1

// Find the next prime number (after p[k])

// Find consequenced prime numbers not greater than sqrt(n)

Trang 36

// so n is a prime number We return n

if (imax == 0) return n; // n is a prime number

return (n < p[imax]) ? p[imax] : n;

float d = difftime(t2,t1);// sec

cout << endl << " Time: " << d << " sec " << endl; cout << "\n\n The result: " << r;

cout << endl << " Fini";

Find the largest palindrome made from the product of two 3-digit numbers

*/

#include <iostream>

#include <stdio.h>;

Ngày đăng: 06/01/2014, 11:10

TỪ KHÓA LIÊN QUAN

w