Wednesday, October 12, 2016

Hướng dẫn nộp bài bằng JAVA trên SPOJ

Chào các bạn! Hôm qua có bạn hỏi mình một số vấn đề khi nộp bài bằng Java trên SPOJ, mình đoán cũng nhiều bạn mới bắt đầu nên còn khá bỡ ngỡ, trước mình cũng loay hoay mãi mới sub được bài Hello World, nên chia sẻ chút mong là bài viết này giúp được phần nào cho các bạn.

Trang chủ SPOJ: http://www.spoj.com/
Trang SPOJ trường mình: http://www.spoj.com/PTIT/
Để sub được bài trên SPOJ thì cần đăng ký nick: http://www.spoj.com/register/ và đăng nhập vào account đã nhé.

Ok, giờ bắt đầu sub các bài basic của trường mình nhé: http://www.spoj.com/PTIT/problems/basic/ những bài này thì thuật toán cũng khá dễ học :D

Trước hết sub bài Hello PTIT nhé: http://www.spoj.com/PTIT/problems/HELLOPOJ/
Bài này chỉ cần in ra dòng chữ "Hello PTIT OJ." là được :D
Bấm nộp bài

Ở trang này:

  1. Chọn ngôn ngữ là Java (Java SE 8u51)
  2. Paste code của bạn vào ô mã nguồn hoặc bấm chọn tệp để chọn file code của bạn. Lưu ý:  Sub code ở đây cũng như ở trang http://ideone.com/Bạn không được để package ở đây, không được để class là  public  nếu không nộp sẽ bị lỗi! (chỉ riêng tên class là Main thì mới được để public thôi)
  3. Bấm nộp bài


Giờ ngồi chờ kết quả thôi :D

Nếu có kết quả xanh là bạn đã code đúng yêu cầu đề bài rồi :D chúc mừng nhé!

Còn nếu sub cam thì có thể rơi vào những trường hợp sau đây:


  • Biên dịch gặp lỗi: Bạn chọn ngôn ngữ sai hoặc do thiếu thư viện
  • SIGSEGV: Khai báo bị tràn mảng. Không được khai báo mảng quá lớn
int []a = new int [100000000];
int [][]b = new int[10000][10000];
  • NZEC: Thường là truy cập đến chỉ số mảng sai (OutOfBoundsException, mảng của bạn khai báo chỉ có 3 phần tử mà bạn lại truy cập đến chỉ số thứ 4,5 chẳng hạn) hoặc do chia 0, input sai (khi nhập xâu bị rỗng chẳng hạn)... 
  • Chạy quá thời gian: Bạn lưu ý thường thì mỗi bài có yêu cầu về thời gian chạy, thường là 1 giây (tương ứng với việc bạn có thể chạy 1 vòng for từ 1 đến 100 triệu thì vẫn được chấp nhận, nhưng đến 1 tỷ thì sẽ bị out) 
  • Làm sai: Lỗi này khi bạn có ouput cho một test nào đó khác với yêu cầu 

Một vài lưu ý khác:

  • Vào ra đều dạng chuẩn, tức là bằng màn hình, tức là dùng luồng System.inSystem.out. 

Bạn có thể tăng tốc vào ra bằng cách thay Scanner System.out bằng các luồng khác như BufferedReader  và BufferedWriter chẳng hạn (Ví dụ như bài này http://www.spoj.com/problems/TSORT/ không thể nào nhập vào bằng Scanner được, quá time ngay!) Đây là code bài này của mình



  • Hãy nhập input và hiển thị output đúng như yêu cầu của đề bài, tức là bạn hãy đọc kỹ đề bài và xem dạng input và output mẫu. Chỉ cần thừa dấu chấm dấu xuống dòng đều có thể nhận "Kết quả sai" đấy!

  • Bạn chỉ được nộp duy nhất 1 file (tức duy nhất 1 class) nên nếu bạn cần tạo 1 class nào khác, hãy để nó là inner static class (để có thể dùng trong hàm main) thì nộp mới được chấp nhận.
    Ví dụ:

  • Lưu ý miền giá trị của input: Ví dụ trong bài xử lý số, nếu đề bài cho số <=10^9 thì các bạn có thể dùng int, còn <=10^18 thì hãy dùng long, còn lớn hơn nữa, thì nên nhập như String rồi xử lý bằng BigInteger xem sao (nếu được cho phép :v). Và cũng có thể trong quá trình tính toán của bạn, số sẽ tràn kiểu, ví dụ số int (max) nhân số int (max) sẽ ra số long chẳng hạn

  • Lưu ý thời gian yêu cầu: Như mình đã nói ở trên, 1 giây ứng với chạy 1 vòng for từ 1 đến 100 triệu, cho nên để không bị quá time, bạn nên tính xem code của mình chạy trong bao lâu, và nếu không thích hợp phải đổi phương án khác. Ví dụ như bài sinh xâu nhị phân độ dài n thì nếu dùng thuật toán sinh sẽ mất 2^n thao tác lặp, vậy nên nếu n=100 chẳng hạn thì không thể chạy trong vòng 1 giây được.


Mẹo vặt linh tinh:
  • Những bài có càng nhiều người sub được hoặc số Tỉ lệ % càng cao thì có vẻ càng dễ, càng có khả năng làm được. Còn nữa, bạn nên bấm vào tag ngôn ngữ JAVA luôn vì có những bài chưa có ai sub nổi bằng ngôn ngữ JAVA => rất khó có thể làm được bằng JAVA, theo mình là không nên đâm đầu vào mà nên thử bài khác hoặc sub bài đấy bằng ngôn ngữ khác. Ví dụ bài này http://www.spoj.com/PTIT/problems/PTIT121H/, chưa hề có ai sub bằng JAVA cả (link minh họa http://www.spoj.com/PTIT/ranks/PTIT121H/lang=JAVA)

  • Ở trang chủ SPOJ: Ví dụ mình đang sub bài này http://www.spoj.com/problems/DIVSUM/ Và cần bộ test thì có thể vào trang này để lấy test : http://spojtoolkit.com/test/DIVSUM/ (bài khác thì thay mã đi là được). Ở đây bạn nhập input và bấm Get Ouput để lấy output và so sánh hoặc bấm Try Available Test Cases để lấy vài testcase mẫu (cẩn thận vì trang này nhiều khi cũng không đúng lắm)

  • Trang ACM PTIT của trường mình: https://www.facebook.com/ACM.PTIT.2013/ có hay đăng solution theo round (bạn nhìn danh mục bên trái trang SPOJ trường mình ấy rồi bấm vào là có thể tìm bài theo từng round). Các bạn có thể vào đây để tìm solution.

  • Còn nữa, một điều cũng khá quan trọng, đó là hầu hết đều đã có code giải, bạn chỉ cần search Google với từ khóa mã bài + chữ "solution" là ra cả, hoặc nếu các bài tiếng Việt thì cũng có nhiều solution rồi, chỉ cần search mã bài là ra, (khi nào bí quá hãy search kiểu khá là hèn hạ này như tớ T_T nhưng mà làm mãi không ra thì ức lắm quá T^T nên theo tớ cứ search ra  nhưng nên gõ lại và hiểu code để áp dụng sau) . 

Cuối cùng, tớ xin chúc các bạn sub XANH! :D




11 comments: