Cách nộp bài trên spoj-Thao tác từ tệp

G

gangoinocnha

[TẶNG BẠN] TRỌN BỘ Bí kíp học tốt 08 môn
Chắc suất Đại học top - Giữ chỗ ngay!!

ĐĂNG BÀI NGAY để cùng trao đổi với các thành viên siêu nhiệt tình & dễ thương trên diễn đàn.

Mình đã nộp bài trên spoj chấm thử,1 số bài thì ok nhưng với những bài bắt buộc phải dùng
lệnh "While not eof(fi) do....." thì chấm toàn bị 0 đ.Mình thử sửa lại While not eof() do..... cũng không được. Sau đó đưa cả chương trình của mình (có cả phần nhập xuất từ tệp) cũng vẫn thế.Bạn nào có thể giúp mình cách giải quyết trường hợp này được không?
 
Last edited by a moderator:
M

mikelhpdatke

Ở phần khai báo hằng, bạn thêm như sau:
Mã:
const fi='';
          fo='';

Thực chất nếu ở máy tính ta sẽ thay = đường dẫn đến các tệp input và output

vd:
Mã:
const fi='Bai1.INP';
          fo='Bai1.OUT';
Var f:text

Nhưng ở trên spoj bạn sẽ khai báo như code ở đầu. Khi cần bạn chỉ cần gọi ra. VD:

Mã:
Assign(f,fi);
Reset(f);
....
Close(f);

Mã:
assign(f,fi)
while not eof(f) do....

PS: Nếu bạn không thích thì bạn làm kiểu bình thường cũng được, tức là nhập dữ liệu từ bạn phím như bình thường, không cần xử lý tệp, vấn tối đa điểm, tuy nhiên có một số bài đặc biệt bắt buộc phải xử lý tệp thôi :)
 
G

gangoinocnha

Cảm ơn bạn.Vậy là khỏi phải khai báo f:text phải không?Việc nhập xuất mình vẫn thực hiện như bình thường đúng không?
VD:Readln(f,n)
 
M

mikelhpdatke

Không bạn ah, vấn phải khai báo
Mã:
f:text
bình thường nhé.

Hoặc đơn giản hơn bạn dùng cách này:

Ở phần khai báo ta vẫn khai báo bình thường.
Mã:
Var f:text
....
..

Còn ở phần thân, khi muốn thao tác với tập chỉ cần gán

Mã:
assign(f,'');
..
..
Close(f);
là ok :)
 
G

gangoinocnha

Bạn xem giùm mình bài này nhé
Đề:
3778. COUNT N
Với 1 số tự nhiên N(1<= N <= 10^9) ta có thể phân tích nó thành tổng của một số số tự nhiên liên tiếp( tất nhiên những số này phải nhỏ hơn N). Ví dụ với N = 5 ta có duy nhất 1 cách phân tích là 5 = 2+3. Bài toán đặt ra là cho số tự nhiên N, hãy cho biết có bao nhiêu cách phân tích số tự nhiên N thành tổng của các số tự nhiên liên tiếp.

Input
Gồm nhiều dòng, mỗi dòng chứa một số nguyên N. (Giới hạn : số dòng <= 100)

Output
Mỗi dòng ghi một số nguyên là số cách phân tích số N đọc được ở dòng tương ứng trong input.

Ví dụ
Input:
12
5
4
13
45
100
234
3
175

Output:
1
1
0
1
5
2
5
1
5
Mình nộp cho spoj như thế này(mình test thử trên máy đúng rồi) nhưng trên spoj chấm

PHP:
Const
fin='';
fon='';
Var
   fi,fo:text;
   a,b,s,d,n,i:longint;    
Procedure tim;
        Begin
                While not eof(fi) do
                begin
                d:=0;
                readln(fi,n);
                For a:=1 to (n div 2) do
                        Begin
                        s:=a;
                        b:=0;
                        Repeat
                           inc(b);
                           s:=s+a+b;
                           If s=n then
                              inc(d);
                        until s>=n;
                        end;
                        Writeln(fo,d);
                 end;
        end;
Begin
d:=0;
Assign(fi,'');
Reset(fi);
Assign(fo,'');
Rewrite(fo);
tim;
Close(fi);
Close(fo);
end.
 
Last edited by a moderator:
M

mikelhpdatke

Cách của bạn là duyệt kiểu dạng "khủng", mất nhiều thời gian.
Mình nghĩ thấy thuật thế này

+ Tổng của các số tự nhiên liên tiếp = (số đầu + số cuối) * số số hạng rồi chia $2$.

$\rightarrow$ Ta có nhận xét đơn giản:

Giả sử $N$ là tổng của các số tự nhiên liên tiếp từ $a$ đến $a+k$, thấy rằng có $k+1$ số hạng nên ta có:

$N = \dfrac{(a+a+k)(k+1)}{2} = \dfrac{(2*a+k)(k+1)}{2}$


Sau đó chỉ cần duyệt rồi kiểm tra thôi.
Còn việc nữa là phải chặn k để duyệt cho nhanh, mình đang nghiên cứu :D
 
Last edited by a moderator:
E

englandhuynh

@mikel : làm theo kiểu này k ổn, theo thuật này phải tìm số đầu & số cuối => 2 vòng lặp đến n div 2 => [TEX]O(25.10^1^7)[/TEX]
Còn hơi "khủng". :khi (47):
 
M

mikelhpdatke

Mình đang cải tiến cách này, có khi phải chặn khoảng một vài biến thì mới ổn, mà có cách nào bạn nói ra xem nào :-?
 
G

gangoinocnha

Bài này có cách nào mà không cần phải đọc trong tệp không, hình như trong spoj sử dụng tệp là 0đ,mấy bài trước mình cũng bị vậy.
Bạn xem giùm mình sai chỗ nào mà spoj chấm 0đ,ở nhà mình cũng chạy được vài test mà.Mình chỉ cần nó chạy được vài test thôi.Còn bài này do thầy mình dạy chiến lược vét cạn nên mình mới vét cạn rồi nộp lên spoj chấm thử.
 
M

mikelhpdatke

Bài test trên mấy đúng nhưng test trên Spoj được 0 đ có thể là do thuật toán của bạn chưa tốt, trên Spoj có nhiều bài yêu cầu khá cao. Hoặc bạn sai ngay từ test đầu tiên, ( test hiểm). Mình test bài của bạn chưa thấy lỗi gì, nhiều khả năng thuật chưa tốt
 
E

englandhuynh

Bài này nếu để ý thì sẽ thấy rằng để phân tích n thành các số tự nhiên liên tiếp thì các số này sẽ gần bằng nhau và số trước chênh với số sau là 1 sử dụng những cách bù vào bớt ra :)) Ta đc nhận xét sau <n số nhập vào, x = n div ...>
+n mod 2 = 1 --> 1 cách (x,x+1)
+n mod 3 = 0 --> 1 cách (x-1,x,x+1)
+n mod 4 = 2 --> 1 cách (x-1,x,x+1,x+2)
+n mod 5 = 0 --> 1 cách (x-2,x-1,x,x+1,x+2)
+n mod 6 = 3 --> 1 cách (x-2,x-1,x,x+1,x+2,x+3)
+n mod 7 = 0 --> 1 cách (x-3,x-2,x-1,x,x+1,x+2,x+3)
+n mod 8 = 4 --> 1 cách (x-3,x-2,x-1,x,x+1,x+2,x+3,x+4)
........
Từ dãy trên thấy có quy luật:
+ Nếu n mod số lẻ = 0 thì inc(c);
+ Nếu n mod số chẵn = số chẵn/2 thì inc(c)
Duyệt i từ 2 đến n-2(giới hạn này có thể tối ưu) nếu thỏa điều kiện trên thì tăng c => đpt là O(10^9), nhỏ hơn nhiều so vs thuật của chú mikel :)
 
G

gangoinocnha

Mình sửa lại chương trình theo thuật toán englandhuynh máy chạy đúng mà vẫn 0đ.Mình đọc trên vnoi có quy định thế này:
Việc nhập và xuất được thực hiện trên thiết bị đọc/ghi chuẩn, do đó khi nộp bài, thí sinh không khai báo đọc/ghi dữ liệu thông qua tập tin, cũng như không được đọc/ghi dữ liệu nhiều lần như trường hợp sử dụng tập tin.
\RightarrowBài này không cho đọc nhiều lần thì phải xử lý làm sao đây?????
 
Last edited by a moderator:
H

hgminh95

@gangoinocnha: Không được đọc nhiều lần có nghĩa là bạn ko thể mở file ra, đọc, đóng file lại rồi mở ra đọc lại, không phải là sử dụng nhiều lệnh read hay readln đâu bạn :))
 
G

gangoinocnha

Mấy bạn xem giúp mình cải tiến chương trình,bài này chạy n<=10^6 thì ok lớn hơn là không chạy nổi.
PHP:
Const
     fin='COUNTCBG.inp';
     fon='COUNTCBG.out';
Var
   fi,fo:text;
   d,n:qword;
   i:longint;
Procedure tim;
        BEGIN
                While not eof(fi) do
                begin
                d:=0;
                readln(fi,n);
                For i:=1 to n div 2 do
                     Begin
                            If (i mod 2)<>0 then
                                begin
                                If (n mod i=0) then inc(d)
                                end
                            else
                            If ((n div i)-((n div 2)-1))>0 then
                                begin
                                If (n mod i)=(i/2) then inc(d)
                                end;
                     End;
                       Writeln(fo,d-1);
                end;
        END;
Begin
d:=0;
Assign(fi,fin);
Reset(fi);
Assign(fo,fon);
Rewrite(fo);
tim;
Close(fi);
Close(fo);
end.
 
Top Bottom