Hỏi bài trên HackerRank: Bit Array
You are given four integers: N, S, P, Q. You will use them in order to create the sequence a with the following pseudo-code.
a[0] = S (modulo 2^31)
for i = 1 to N-1
a[i] = a[i-1]*P+Q (modulo 2^31)
Your task is to calculate the number of distinct integers in the sequence a.
Input Format
Four space separated integers on a single line N, S, P and Q respectively.
Output Format
A single integer that denotes the number of distinct integers in the sequence a.
Constraints
1 <= N <= 10^8
0 <= S, P, Q < 2^31
Sample Input
3 1 1 1
Sample Output
3
Explanation
a = [1, 2, 3]
Hence, there are 3 different integers in the sequence.
o0o
Bạn nào hiểu thì giải thích lại dùm mình.
Cho 4 số nguyên N, S, P, Q. Tạo N số ai với quy luật:
Hỏi trong N số ai đó có bao nhiêu số khác nhau đôi một (distinct integers)?
Ràng buộc:
1 ≤ N ≤ 108
1 ≤ S, P, Q < 231
cái tên của bài là Bit Array nghĩa là gợi ý xài mảng bit. Với quy luật trên thì ta có 0 ≤ ai < 231 (vì ai có % 231) thì tối đa có 231 số khác nhau đôi một. Nếu tạo 1 `set` rồi mỗi lần sinh ra ai thì cho ai vào set này thì sẽ ngốn ram rất nhiều vì size của set có thể lên tới 2 tỷ phần tử => vài chục GB RAM. Cách giải là tạo mảng bit `a` gồm 231 phần tử luôn, mỗi phần tử chỉ chiếm 1 bit => 231 phần tử chỉ chiếm 256MB RAM. Mỗi lần sinh ai thì gán `a[i] = 1`. Sau đó nếu tại vị trí i nào mà `a[i]==0` thì ai ko xuất hiện trong dãy số trên. Từ đó đếm được số lương số khác nhau đôi một.
Mình làm mà nó chỉ pass test case mẫu, còn các test case khác thì fail
Bạn có thể coi qua bài mình làm và chỉ ra chỗ sai của mình. Cám ơn !
Bài mình làm bằng code java
đâu có đúng. a trỏ tới mảng int, a[0] là int - 32 bit chứ đâu phải là 1 bit. Mình viết có lẽ chưa kỹ: tính được ai thì set visited[ai] = 1 chứ ko phải set visited[i] = 1. Mình viết “set a[i] = 1 khi tính được ai” là viết tắt cho kiểu này.
C++ có kiểu
vector<bool>
là bit array đó, lấy nó mà xài.rồi sau đó bạn có thể đếm số lượng bit 1 trong bit array
visited
:nhưng làm kiểu này rất là lâu, vì phải lướt 231 phần tử. Trong khi n < 108, nên đếm trong vòng for ở trên. Mình để bạn tự suy nghĩ vậy ha. Gợi ý là trong vòng lặp trên, chỉ cộng 1 cho result khi chưa gặp
a
. Nếu đã gặpa
rồi (visited[a] == true) thì ko cộng 1.thử với input
10000 573272257 859433109 1894136138
output là 10000. Xem nó chạy ná thở luôn vì
length
lên tới hơn 2 tỷ. N giới hạn là 100 triệu nên đếm ở trong vòng lặp N ấy.Ok, thế để mình update, hehe
100000000 569099406 1607140150 823906344
output 31. Mình bị fail test case, nhưng cuối cùng cũng pass
Cám ơn bạn !
Bạn cho mình hỏi thêm: giả sử mình tính
a
i
= 123
thì tương ứng với vị trí thứ123
trong Bit Array và bật lên 1 đúng không?đúng rồi. Nhưng trước khi bật xem vị trí thứ 123 có được bật chưa, tức là số 123 đã xuất hiện trước đó chưa, nếu đã có rồi thì đừng đếm nó, nếu chưa có thì mới đếm.