Bộ phận số nguyên chính xác tùy ý


16

Chúng tôi sẽ thực hiện phân chia cho số nguyên lớn tùy ý.

Đây là .

Nhiệm vụ là viết một chương trình hoặc hàm thực hiện các số nguyên chính xác tùy ý và Phân chia trên chúng.

Lưu ý rằng nhiều thứ có thể làm cho việc này rất dễ dàng không được phép, vui lòng đảm bảo đọc qua thông số kỹ thuật .

Đầu vào

Bạn sẽ được cung cấp 2 thứ làm đầu vào:

  1. một chuỗi gồm 10 chữ số cơ bản, gọi nó n.
  2. một chuỗi gồm 10 chữ số cơ bản, gọi nó m

Giả sử rằngn>m>0 có nghĩa là bạn sẽ không bao giờ được yêu cầu chia cho số không .

Đầu ra

Bạn sẽ xuất hai số QRtrong đó m * Q + R = n0 <= R <m

Thông số kỹ thuật

  • Việc gửi của bạn phải hoạt động đối với các số nguyên lớn tùy ý (giới hạn bởi bộ nhớ khả dụng).

  • Bạn không thể sử dụng các thư viện bên ngoài. Nếu bạn cần một thư viện bên ngoài cho i / o, bạn có thể coi nó là một thư viện tích hợp. (nhìn vào những thứ như iostream, v.v.).

  • Nếu ngôn ngữ của bạn có tích hợp sẵn tầm thường hóa điều này, bạn không thể sử dụng ngôn ngữ đó. Điều này bao gồm (nhưng có thể không giới hạn ở) các loại tích hợp có thể xử lý các số nguyên chính xác tùy ý.

  • Nếu một ngôn ngữ vì một lý do nào đó sử dụng các số nguyên chính xác tùy ý theo mặc định, chức năng này không thể được sử dụng để biểu diễn các số nguyên không thể được lưu trữ trong 64 bit.

  • Đầu vào và đầu ra PHẢI ở cơ sở 10 . Việc bạn lưu trữ các số trong bộ nhớ không quan trọng hay cách bạn thực hiện số học trên chúng, nhưng i / o sẽ là cơ sở 10.

  • Bạn có 15 giây để xuất kết quả. Điều này là để cấm phép trừ lặp.

  • Mục tiêu ở đây là để thực sự thực hiện các số nguyên chính xác tùy ý. Nếu vì lý do nào đó bạn có thể tuân thủ các thông số kỹ thuật thách thức và thực hiện thành công điều này mà không thực hiện chúng, thì tôi đoán tốt cho bạn, nghe có vẻ hợp lệ.

Các trường hợp thử nghiệm

  1. Trong trường hợp này, đầu vào là 39! và 30!

Đầu vào

n = 20397882081197443358640281739902897356800000000 
m = 265252859812191058636308480000000

Đầu ra

Q = 76899763100160
R = 0
  1. nlà tổng của tất cả các giai thừa lên tới 50, cộng với 1. mlà các số được nối lên tới 20.

đầu vào

n = 31035053229546199656252032972759319953190362094566672920420940313
m = 1234567891011121314151617181920

đầu ra

q = 25138393324103249083146424239449429
r = 62459510197626865203087816633
  1. nlà 205! + 200!. mPeterTaylor đã làm tôi rơi bao nhiêu nước mắt bằng cách xé tan những thứ tôi đăng trong hộp cát.

Đầu vào

n = 271841734957981007420619769446411009306983931324177095509044302452019682761900886307931759877838550251114468516268739270368160832305944024022562873534438165159941045492295721222833276717171713647977188671055774220331117951120982666270758190446133158400369433755555593913760141099290463039666313245735358982466993720002701605636609796997120000000000000000000000000000000000000000000000000
m = 247

Đầu ra

q = 1100573825740813795225181252819477770473619155158611722708681386445423816849801159141424129060075102231232666057768175183676764503262931271346408394876267875141461722640873365274628650676808557279259873162169126398101692109801549256156915750794061370041981513180387019893765753438422927286098434193260562682052606153857091520795991080960000000000000000000000000000000000000000000000000
r = 0;

Có thể tôi sẽ thêm nhiều trường hợp thử nghiệm tại một số điểm.

Liên quan

Âm thanh liên quan, nhưng thực sự không


Có thư viện IO được tính là thư viện bên ngoài?
Johnson Steward

@JohnsonSteward Tôi không chắc ý của bạn là gì? Tôi sẽ mặc định là "có", nhưng bạn có thể làm rõ không?
Liam

@JohnsonSteward Tôi cho rằng nó phụ thuộc vào những gì bạn đang IOing? Có phải là mã / một thư viện mã?
Ashwin Gupta

1
Số âm có được phép không?
TheConstructor

2
@TheConstructor: từ các quy tắc: "giả sử rằng n> m> 0", vì vậy không, số âm không được phép.
nimi

Câu trả lời:


4

Python 2, 427 byte

b=S=lambda l:sorted(l)[::-1]
A=lambda a,b,o=0:A(a^b,{n+1for n in[b&a,b-a][o]},o)if b else a
M=lambda a,*b:reduce(A,({n+m for n in a}for m in b))
def D(a,b):
 q=a-a
 while b<=S(a):n=max(a)-b[0];n-=S(M(b,n))>S(a);q|={n};a=A(a,M(b,n),1)
 return q,a
exec"a=b;b=[]\nfor d in raw_input():b=A(M(b,3,1),{i for i in range(4)if int(d)>>i&1})\n"*2
for n in D(a,S(b)):
 s=''
 while n:n,d=D(n,[3,1]);s=`sum(2**i for i in d)`+s
 print s or 0

Đọc đầu vào thông qua STDIN, mỗi số trên một dòng riêng biệt và in kết quả ra STDOUT.

Giải trình

Thay vì biểu diễn các số nguyên dưới dạng các mảng chữ số, chúng tôi biểu diễn mỗi số nguyên dưới dạng tập hợp các bit "bật" trong biểu diễn nhị phân của nó. Nghĩa là, một số nguyên n được biểu diễn dưới dạng tập hợp các chỉ số của các bit bằng 1 trong biểu diễn nhị phân của n . Ví dụ: số 10, 1010 ở dạng nhị phân, được biểu diễn dưới dạng tập {1, 3}. Biểu diễn này cho phép chúng tôi thể hiện một số thao tác số học khá ngắn gọn, bằng cách sử dụng các hoạt động thiết lập của Python.

Để thêm hai tập hợp, chúng tôi (đệ quy) lấy tổng của sự khác biệt đối xứng của chúng và tập hợp các số nguyên tiếp theo với giao điểm của chúng (tương ứng với tập hợp mang theo, và cuối cùng trở thành tập hợp trống, tại đó chúng tôi có tổng cuối cùng .) Tương tự, để trừ hai tập hợp, chúng tôi (đệ quy) lấy sự khác biệt về chênh lệch đối xứng của chúng và tập hợp các số nguyên tiếp theo với chênh lệch (tập hợp) của chúng (tương ứng với vay tập thể, và cuối cùng trở thành tập hợp trống, tại điểm nào chúng ta có sự khác biệt cuối cùng.) Sự giống nhau của hai thao tác này cho phép chúng ta thực hiện chúng như một hàm duy nhất ( A).

Phép nhân ( M) là phép cộng phân phối đơn giản: cho hai tập hợp AB , chúng ta lấy tổng, như mô tả ở trên, của tất cả các tập { A + b | bB } (trong đó A + b là tập { a + b | aA }).

So sánh số nguyên trở thành so sánh từ vựng của hai bộ, được sắp xếp theo thứ tự giảm dần.

Để chia ( D) hai tập hợp AB , chúng ta bắt đầu với tập hợp trống là thương số và liên tục tìm số nguyên n lớn nhất , sao cho B + n nhỏ hơn hoặc bằng A (đơn giản là sự khác biệt giữa cực đại của AB , có thể trừ đi 1), thêm n làm phần tử cho thương số và trừ B + n khỏi A , như mô tả ở trên, cho đến khi A trở thành nhỏ hơn B , nghĩa là cho đến khi nó trở thành phần còn lại.

Không có bữa trưa miễn phí, tất nhiên. Chúng tôi trả thuế bằng cách chuyển đổi từ- và sang-, thập phân. Trong thực tế, việc chuyển đổi sang số thập phân là phần lớn thời gian chạy. Chúng tôi thực hiện chuyển đổi "theo cách thông thường", chỉ sử dụng các thao tác trên, thay vì số học thông thường.


Vì tò mò: không s=`sum(2**i for i in d)`+ssử dụng số học chính xác tùy ý tích hợp trong quá trình chuyển đổi?
TheConstructor

1
Số @TheConstructor dlà một chữ số thập phân duy nhất, inằm trong khoảng từ 0 đến 3 và toàn bộ tổng nằm trong khoảng từ 0 đến 9.
Ell

4

Java 8, 485 byte

Có thể giảm thêm 5 byte khi đặt tên hàm dthay vì dividehoặc 16 byte khác nếu không tính định nghĩa lớp.

public class G{int l(String a){return a.length();}String s(String n,String m){while(l(n)>l(m))m=0+m;String a="";for(int c=1,i=l(n);i>0;c=c/10){c=n.charAt(--i)+c-m.charAt(i)+9;a=c%10+a;}return e(a);}String e(String a){return a.replaceAll("^0+(?=[0-9])","");}String divide(String n,String m){String q="",p=q,y;for(int b=0,i=0;b<=l(n);i--){y=n.substring(0,b);if(l(y)==l(p)&&p.compareTo(y)<=0||l(y)>l(p)){y=s(y,p);n=y+n.substring(b);q+=i;b=l(y)+1;i=10;p=m+0;}p=s(p,m);}return e(q)+","+n;}}

Có thể được sử dụng như thế này:

public static void main(String[] args) {
    G devision = new G();
    System.out.println(devision.divide("20397882081197443358640281739902897356800000000",
            "265252859812191058636308480000000"));
    System.out.println(devision.divide("31035053229546199656252032972759319953190362094566672920420940313",
            "1234567891011121314151617181920"));
    System.out.println(devision.divide(
            "271841734957981007420619769446411009306983931324177095509044302452019682761900886307931759877838550251114468516268739270368160832305944024022562873534438165159941045492295721222833276717171713647977188671055774220331117951120982666270758190446133158400369433755555593913760141099290463039666313245735358982466993720002701605636609796997120000000000000000000000000000000000000000000000000",
            "247"));
}

năng suất

76899763100160,0
25138393324103249083146424239449429,62459510197626865203087816633
1100573825740813795225181252819477770473619155158611722708681386445423816849801159141424129060075102231232666057768175183676764503262931271346408394876267875141461722640873365274628650676808557279259873162169126398101692109801549256156915750794061370041981513180387019893765753438422927286098434193260562682052606153857091520795991080960000000000000000000000000000000000000000000000000,0

Ung dung:

public class ArbitraryPrecisionDivision {

    /**
     * Length of String
     */
    int l(String a) {
        return a.length();
    }

    /**
     * substract m of n; n >= m
     */
    String s(String n, String m) {
        while (l(n) > l(m))
            m = 0 + m;
        String a = "";
        for (int c = 1, i = l(n); i > 0; c = c / 10) {
            c = n.charAt(--i) + c - m.charAt(i) + 9;
            a = c % 10 + a;
        }
        return e(a);
    }

    /**
     * trim all leading 0s
     */
    String e(String a) {
        return a.replaceAll("^0+(?=[0-9])", "");
    }

    /**
     * divide n by m returning n/m,n%m; m may not start with a 0!
     */
    String divide(String n, String m) {
        // q stores the quotient, p stores m*i, y are the b leading digits of n
        String q = "", p = q, y;
        for (int b = 0, i = 0; b <= l(n); i--) {
            y = n.substring(0, b);
            if (l(y) == l(p) && p.compareTo(y) <= 0 || l(y) > l(p)) {
                y = s(y, p);
                n = y + n.substring(b);
                q += i;
                b = l(y) + 1;
                i = 10;
                p = m + 0;
            }
            p = s(p, m);
        }
        return e(q) + "," + n;
    }

    public static void main(String[] args) {
        ArbitraryPrecisionDivision division = new ArbitraryPrecisionDivision();
        System.out.println(division.divide("20397882081197443358640281739902897356800000000",
                "265252859812191058636308480000000"));
        System.out.println(division.divide("31035053229546199656252032972759319953190362094566672920420940313",
                "1234567891011121314151617181920"));
        System.out.println(division.divide(
                "271841734957981007420619769446411009306983931324177095509044302452019682761900886307931759877838550251114468516268739270368160832305944024022562873534438165159941045492295721222833276717171713647977188671055774220331117951120982666270758190446133158400369433755555593913760141099290463039666313245735358982466993720002701605636609796997120000000000000000000000000000000000000000000000000",
                "247"));
    }
}

Tôi đã hy sinh một chút tốc độ bằng cách không tính toán trước một mảng với các mlần từ 1 đến 9 và bắt đầu bằng b=0thay vì b=l(m), nhưng đã lưu rất nhiều byte làm như vậy. Nếu bạn quan tâm đến việc bổ sung độ chính xác tùy ý, hãy xem phiên bản trước .

Tôi đoán đây sẽ không phải là giải pháp ngắn nhất, nhưng có lẽ nó mang lại một khởi đầu tốt.


Nếu bạn cũng thực hiện phép cộng, phép nhân và phép trừ cho điều này, tôi sẽ kiếm được 500 điểm thưởng cho việc này. : DI thích ý tưởng về độ chính xác của Stringy.
Addison Crump

@VoteToClose sẽ thấy vào ngày mai. Đoán phần khó nhất được thực hiện.
TheConstructor

1

Toán học, 251 byte

r=Reverse;f=FoldPairList;s={0}~Join~#&;
p[a_,b_]:={First@#,#[[2,1,-1,2]]}/.{Longest[0..],x__}:>{x}&@Reap@f[Sow@{Length@#-1,Last@#}&@NestWhileList[r@f[{#~Mod~10,⌊#/10⌋}&[#+Subtract@@#2]&,0,r@Thread@{#,s@b}]&,Rest@#~Join~{#2},Order[#,s@b]<=0&]&,0s@b,s@a]

Giải trình

Arithologists trên số thập phân có thể dễ dàng được thực hiện bởi FoldPairList. Ví dụ,

times[lint_,m_]:=Reverse@FoldPairList[{#~Mod~10,⌊#/10⌋}&[m #2+#]&,0,Reverse@lint]

chỉ bắt chước quá trình thực hiện phép nhân bằng tay.

times[{1,2,3,4,5},8]
(* {9,8,7,6,0} *)

Trường hợp thử nghiệm

p[{1,2,3,4,5,6,7,8,9},{5,4,3,2,1}] 
(* {{2,2,7,2},{3,9,4,7,7}} *)

có nghĩa là 123456789 / 54321= 2272...39477.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.