thảo luận [Học Tập] Topic thuật toán

Chủ thớt code bài này như nào mà tạch?

Đây thím ơi, nó tạch một test số super lớn
1622534680551.png
 
Vấn đề là a vs b rất lớn, 10^(100000) thì quá cả long rồi, nên phải xử lý. A cho link đề gốc trên Codeforces đi để tối tôi về thử. Nếu n là prime thì có thể dùng little fermat theorem. Trong th này thì hình như là ko nên khó hơn nhiều.
đúng r thím,em nghĩ là phải tách cái n ra prime xử lý r hợp lại mà em chưa nghĩ ra hợp kiểu gì cho đúng, link thì contest private nên ko có thím ơi
 
Chắc phải cài đặt bigint rồi, cũng không cần tối ưu quá vì chỉ dùng một lần. Sau đó sẽ tính những thứ sau:

a' = a % n
b' = biểu diễn nhị phân của b

sau đó dùng thuật toán powermod như bình thường.
 
Đây thím ơi, nó tạch một test số super lớn
View attachment 576687

Chỗ hàm calculate có vẻ sai. Cái for-loop đầu tiên để tính modulo cho num thì ok. Còn cái forloop thứ 2 tính modulo cho pow_it thì hog đúng. Nó sai về mặt ý nghĩa đó, a^p % n sẽ khác với (a % n)^(p % n) % n

Chỗ này nên lấy modulo cho num thôi, rồi sau đó loop trên từng kí tự của string pow_it
 
Chỗ hàm calculate có vẻ sai. Cái for-loop đầu tiên để tính modulo cho num thì ok. Còn cái forloop thứ 2 tính modulo cho pow_it thì hog đúng. Nó sai về mặt ý nghĩa đó, a^p % n sẽ khác với (a % n)^(p % n) % n

Chỗ này nên lấy modulo cho num thôi, rồi sau đó loop trên từng kí tự của string pow_it
để em thử lại xem sao
 
a^b % n == (a%n)^b % n thì phải
TG0OxM9.gif

à chưa kể ko cần mũ b đâu mà mũ 1 số x nào đó < n thoy
TG0OxM9.gif

Chỉ áp dụng được khi a và n nguyên tố cùng nhau.
Dùng định lý Euler: a ^ b mod n = a ^ (k*phi(n) +b') mod n = a ^ b' mod n
Trong đó phi(n) là số số nguyên tố cùng nhau với n và nhỏ hơn n.
 
Đây thím ơi, nó tạch một test số super lớn
View attachment 576687
vậy thớt tạch là do tính pow_it % mod là sai nè. Phải tính thẳng với string b luôn. Viết thêm 1 hàm chia 2 cho chuỗi số nguyên vd half("123") = "61". Cơ mà chia như vậy hóa ra O(n^2) gì mất rồi
aVgiONl.png

à như brint nói biến đổi b thành chuỗi nhị phân trước vậy là ok O(n) với n ~ 3x10^5 hình như cũng chậm O(n^2)? :V
 
Last edited:
ồ phân tích b theo kiểu này là được, ví dụ b = 123456 thì phân tích b thành 100000 + 20000 + 3000 + 400 + 50 + 6 hay 1x10^5 + 2x10^4 + 3x10^3 + 4x10^2 + 5x10^1 + 6. Chỉ cần tính a^(10^i) % n từ từ là được.
 
ồ phân tích b theo kiểu này là được, ví dụ b = 123456 thì phân tích b thành 100000 + 20000 + 3000 + 400 + 50 + 6 hay 1x10^5 + 2x10^4 + 3x10^3 + 4x10^2 + 5x10^1 + 6. Chỉ cần tính a^(10^i) % n từ từ là được.
B range nó 10^10^5 lận thím, phân tích kiểu này sao tính nổi thím nhỉ, nó vượt quá kiểu long long r
 
nipetvn làm đúng rồi mà fen vẫn ko hiểu à. Thế thì bài này hơi quá tầm vs fen rồi.
Ví dụ:

a^ab = (a^a)^10*a^b

a^abc = ((a^a)^10*a^b)^10*a^c
....
Rồi cứ thế thôi, đi từ index 0 đến index cuối của string, cứ mỗi index thì ^10 số trước lên rồi nhân vs mũ của giá trị tại index đó.
Java:
long result = 1;
long a = // value of string a mod n
for(int i = 0; i < b.length(); i++){
    int val = b.charAt(i) - 'a';
    result = pow(result, 10)*pow(a, val);
    result %= n;
}
Hàm mũ pow ở trên tôi giả sử là đã xử lý mod n bên trong rồi.
 
Last edited:
B range nó 10^10^5 lận thím, phân tích kiểu này sao tính nổi thím nhỉ, nó vượt quá kiểu long long r
ví dụ "1729"^"8954" % 100 đi (dấu " " là cho chuỗi)

lấy a % n theo kiểu từ từ như trên kia:
1 % 100 = 1
(1*10 + 7) % 100 = 17
(17*10 + 2) % 100 = 72
(72*10 + 9) % 100 = 29

vậy bài toán chuyển thành 29^"8954" % 100. 29 là số nguyên, 100 là số nguyên, "8954" là chuỗi.

Nhận thấy là
29^"8954"
= 29^8000 * 29^900 * 29^50 * 29^4
= 29^4 * 29^50 * 29^900 * 29^8000
= (29^1)^4 * (29^10)^5 * (29^100)^9 * (29^1000)^8

Như vậy có thể viết thành vòng lặp, ban đầu đặt a' = 29, rồi vòng lặp tiếp theo tính a' = a'^10 để tính 29^1, 29^10, 29^100, 29^1000. Số 4, 5, 9, 8 kia có thể lấy từ chuỗi "8954" theo chiều ngược lại.

pseudocode:
Swift:
func pow(a: str, b: str, n: int) -> int {
  let res:int = 1
  let a′:int = mod_str_int(a, n)
  let b′:str = reverse_str(b)
  for c:chr in b′ do {
    let d:int = digit_chr_to_int(c)
    res = res * mod_pow(a′, d, n) % n // tính (29^1)^4 * (29^10)^5 * (29^100)^9 * (29^1000)^8
    a′ = mod_pow(a′, 10, n)           // tính 29^1, 29^10, 29^100, 29^1000
  }
  return res
}

func mod_str_int(a: str, n: int) -> int { ... } // "1729" % 100 -> 29
func reverse_str(s: str) -> str { ... }
func digit_chr_to_int(c: chr, n: int) -> int { ... }
func mod_pow(a: int, b: int, n: int) -> int { ... }
// tạm để lang=swift cho có màu đọc đỡ đau mắt chứ ko phải swift nha
// edit res init value = 1 chứ ko phải = 0
Dcnffay.png
 
Last edited:
Đào lên nào là đào lên nào.
Câu này không nhớ bị hỏi ở đâu nhưng đơn giản nó thế này:

Đọc một dãy số ra chữ bằng tiếng Anh. Điều kiện: input bất kỳ số nào

Ví dụ:

Input: 1999
Output: One thousand nine hundred ninety nine

Input: 1021
Output: One thousand twenty one

Input: 101
Output: One hundred and one

Input: 11
Output: Eleven
 
Đào lên nào là đào lên nào.
Câu này không nhớ bị hỏi ở đâu nhưng đơn giản nó thế này:

Đọc một dãy số ra chữ bằng tiếng Anh. Điều kiện: input bất kỳ số nào

Ví dụ:

Input: 1999
Output: One thousand nine hundred ninety nine

Input: 1021
Output: One thousand twenty one

Input: 101
Output: One hundred and one

Input: 11
Output: Eleven
Ngày trước làm bài này rồi nhưng bằng tiếng việt
 
Đào lên nào là đào lên nào.
Câu này không nhớ bị hỏi ở đâu nhưng đơn giản nó thế này:

Đọc một dãy số ra chữ bằng tiếng Anh. Điều kiện: input bất kỳ số nào

Ví dụ:

Input: 1999
Output: One thousand nine hundred ninety nine

Input: 1021
Output: One thousand twenty one

Input: 101
Output: One hundred and one

Input: 11
Output: Eleven
Này là câu hard trên leetcode
 
Đào lên nào là đào lên nào.
Câu này không nhớ bị hỏi ở đâu nhưng đơn giản nó thế này:

Đọc một dãy số ra chữ bằng tiếng Anh. Điều kiện: input bất kỳ số nào

Ví dụ:

Input: 1999
Output: One thousand nine hundred ninety nine

Input: 1021
Output: One thousand twenty one

Input: 101
Output: One hundred and one

Input: 11
Output: Eleven
JavaScript:
function convertNumber(num){
  let lookup =['Không','Một','Hai','Ba','Bốn','Năm','Sáu','Bảy','Tám','Chín'];

  array = Array.from(num.toString());
  X = array.map(item => lookup[item]).reverse();

  for(let i = 0; i < X.length; i++){

    let alt = ['','Nghìn','Triệu'];

    if(i%3 == 0){
      if(X[i] == 'Không') X[i] = alt[i/3]
      else X[i]+= ' ' + alt[i/3];
    }

    if(i%3 == 1){
      if(X[i] == 'Không') {
        if(alt.includes(X[i-1])) X[i] = '';
        else X[i] = 'Linh';
      }
      else if(X[i] == 'Một') X[i] = 'Mười';
      else X[i]+= ' Mươi';
    }

    if(i%3 == 2) X[i]+= ' Trăm';
  }

  X = X.filter(item => item!=='');
  return X.reverse().join(' ').replace(/Không Trăm Nghìn/,'').replace(/Không Trăm$/,'');
}

console.log(convertNumber(110200100));
 
JavaScript:
function convertNumber(num){
  let lookup =['Không','Một','Hai','Ba','Bốn','Năm','Sáu','Bảy','Tám','Chín'];

  array = Array.from(num.toString());
  X = array.map(item => lookup[item]).reverse();

  for(let i = 0; i < X.length; i++){

    let alt = ['','Nghìn','Triệu'];

    if(i%3 == 0){
      if(X[i] == 'Không') X[i] = alt[i/3]
      else X[i]+= ' ' + alt[i/3];
    }

    if(i%3 == 1){
      if(X[i] == 'Không') {
        if(alt.includes(X[i-1])) X[i] = '';
        else X[i] = 'Linh';
      }
      else if(X[i] == 'Một') X[i] = 'Mười';
      else X[i]+= ' Mươi';
    }

    if(i%3 == 2) X[i]+= ' Trăm';
  }

  X = X.filter(item => item!=='');
  return X.reverse().join(' ').replace(/Không Trăm Nghìn/,'').replace(/Không Trăm$/,'');
}

console.log(convertNumber(110200100));
Đề là tiếng Anh mà? Luật nó cũng khác nhau. Mà cuối cùng ông làm về ngôn ngữ gì thế? Sao chuyển qua JS rồi?
 
Back
Top