Hiển thị các bài đăng có nhãn Sinh. Hiển thị tất cả bài đăng
Hiển thị các bài đăng có nhãn Sinh. Hiển thị tất cả bài đăng
P173PROG - ROUND 3G - Biến đổi xâu kí tự

P173PROG - ROUND 3G - Biến đổi xâu kí tự

Link Sub: http://www.spoj.com/PTIT/problems/P173PROG/
Người Gửi: Dương Lee

  • Problem:

Cho 1 xâu kí tự s, hãy sắp xếp lại vị trí của các kí tự trong xâu để được một xâu p mới thoả mãn thứ tự từ điển của p lớn hơn thứ tự từ điển của s. Trong trường hợp có nhiều đáp án, tìm kết quả có thứ tự từ điển nhỏ nhất.
Input
Dòng đầu tiên gồm 1 số nguyên dương t – số lượng test (t < 100 001).  
t dòng tiếp theo mỗi dòng chứa 1 xâu kí tự s  
(0 < |s| < 101, xâu kí tự chỉ gồm các chữ cái tiếng Anh viết thường).
Output
Với mỗi test, in ra 1 dòng là xâu kí tự p có thứ tự từ điển lớn hơn xâu s. Nếu không có kết quả, in ra "BIGGEST" (không có dấu ngoặc kép).
Example:
Input
4
ccd
tv
wolf
fnf
Output:
cdc
vt
BIGGEST
nff

  • Solution:

Bài này thực chất là sinh hoán vị kết tiếp. Nếu không sinh tiếp được thì đó là xâu lớn nhất.

  • Code:

C++:

https://ideone.com/eSi8n0
#include <iostream>
using namespace std;

string HV_kt (string s)
{
    int n = s.length();
    int i = n - 1 - 1;
    while (i>=0 && s[i]>=s[i+1]) i--;
    if (i>=0)
    {
        int vt;
        for (int j = n-1; j>=0; j--)
            if (s[j]>s[i])
            {
                vt = j;
                break;
            }
        
        char tmp = s[vt];
        s[vt] = s[i];
        s[i] = tmp;
        
        int l = i+1, r=n-1;
        while (l<=r)
        {
            tmp = s[l];
            s[l] = s[r];
            s[r] = tmp;
            
            l++;
            r--;
        }
        return s;
    }
    return "BIGGEST";
}

int main ()
{
    int t;
    cin>>t;
    string s;
    while (1)
    {
        if (t==0) break;
        t--;
        cin>>s;
        cout<<HV_kt (s)<<endl;
    }
    return 0;
}

JAVA:

...

Python:

...

P146PROA - ROUND 6A - Lật xu

Link Sub: http://www.spoj.com/PTIT/problems/P146PROA/
Người Gửi: Dương Lee

  • Problem:

Có 16 đồng xu xếp thành bảng 4x4, mỗi đồng xu có thể úp hoặc ngửa như hình vẽ bên.
Tại mỗi bước ta có phép biến đổi sau: Chọn một đồng xu và thay đổi trạng thái của đồng xu đó và tất cả các đồng xu nằm ở các ô chung cạnh (úp thành ngửa, ngửa thành úp).  
Yêu cầu: Cho trước một trạng thái các đồng xu, hãy lập trình tìm số phép biến đổi ít nhất để đưa về trạng thái tất cả các đồng xu hoặc đều úp hoặc đều ngửa.
Input
Gồm 4 dòng, mỗi dòng gồm 4 kí tự miêu tả trạng thái của mỗi đồng xu. Kí tự ‘w’ (white) thể hiện đồng xu đang ngửa, kí tự ‘b’ (black) thể hiện đồng xu úp.
Output
In ra số phép biến đổi ít nhất để đưa 16 đồng xu về tất cả trạng thái đều úp hoặc đều ngửa. Nếu không thể thực hiện được, in ra ”Impossible”.
Example:
Input
wbwb
bwbw
wbwb
bwbw
Output:
Impossible

Input
bwbb
wwwb
bwbb
bbbb
Output:
1
  • Solution:

- Bài này sinh nhị phân chọn lật đồng xu (Ở đây mình sinh nhị phân trên mảng 1 chiều rồi chuyển sang 2 chiều). - Code dưới đây nếu giá trị là 1 thì chọn lật đồng xu đó (đồng thời cũng lật các đồng xu xung quanh nó), nếu giá trị là 0 thì giữ nguyên. - Sau đó kiểm tra lại xem nó có cùng úp hoặc ngửa hay không? nều cùng thì số lượng giá trị 1 là số lần đổi và ta chỉ cần lấy min là được.

  • Code:

C++:

https://ideone.com/UWP7Hb

#include <iostream>
#include <math.h>
using namespace std;

char info[5][5];
void read ()
{
    for (int i=1; i<=4; i++)
    {
        for (int j=1; j<=4; j++)
        cin>>info[i][j];
    }
}

int arr[25];
int coins[5][5];
int _1Dto2D ()
{
    int k=1;
    int count = 0;
    for (int i=1; i<=4; i++)
    {
        for (int j=1; j<=4; j++)
        {
            coins[i][j]=arr[k];
            if (arr[k]==1) count++;
            k++;
        }
    }
    return count;
}

char rs[5][5];
int x_xq[]={+1, +0, -1, +0};
int y_xq[]={+0, -1, +0, +1};
void latxu ()
{
    //Cop:
    for (int i=1; i<=4; i++)
    {
        for (int j=1; j<=4; j++)
        rs[i][j]=info[i][j];
    }
    for (int i=1; i<=4; i++)
    {
        for (int j=1; j<=4; j++)
        {
            if (coins[i][j]==1)
            {
                if (rs[i][j]=='b') rs[i][j]='w';
                else rs[i][j]='b';
                for (int k=0; k<4; k++)
                {
                    int X=j+x_xq[k];
                    int Y=i+y_xq[k];
                    if (X>=1 && X<=4 && Y>=1 && Y<=4)
                    {
                        if (rs[Y][X]=='b') rs[Y][X]='w';
                        else rs[Y][X]='b';
                    }
                }
            }
        }
    }
}

int check ()
{
    char init = rs[1][1];
    for (int i=1; i<=4; i++)
    {
        for (int j=1; j<=4; j++)
        {
            if (rs[i][j]!=init) return 0;
        }
    }
    return 1;
}

char tt[5][5];
int t2[5][5];

int Ans = 25;
void sinhNP (int u)
{
    if (u>16)
    {
        int x = _1Dto2D ();
        latxu ();
        if (check()==1) Ans = min (Ans, x);
    }
    else
    {
        arr[u]=0;
        sinhNP (u+1);
        arr[u]=1;
        sinhNP (u+1); 
    }
}

int main ()
{
    read ();
    sinhNP (1);
    if (Ans != 25) cout<<Ans;
    else cout<<"Impossible";
    return 0;
}


JAVA:


PTIT017J - ACM PTIT 2017 J - SỐ CÁC SỐ KHÔNG CHIA HẾT

Link Sub: http://www.spoj.com/PTIT/problems/PTIT017J/
Người Gửi: Dương Lee

  • Problem:

Cho 5 số tự nhiên a, b, c, d, e là các số nguyên tố cùng nhau từng đôi một. Hãy cho biết có bao nhiêu số nhỏ hơn hoặc bằng N không chia hết cho bất kỳ số nào trong các số a, b, c, d, e (N<263
Input
Dòng đầu tiên là số lượng bộ test T (T ≤ 50). 
Mỗi test gồm hai dòng:  dòng đầu tiên ghi lại số N, dòng kế tiếp ghi lại 5 số a, b, c, d, e nguyên tố cùng nhau (cả 5 số đều không quá 1000).
Output
Ứng với mỗi test đưa ra số lượng các số không chia hết cho bất kể số nào trong các số a, b, c, d, e
Example:
Input
3
1000
2 3 5 7 11
10000
3 4 5 7 11
1000000000
9 11 13 17 19
Output:
207
3116
665093420

  • Solution:

- Bài này dựa vào toán rời rạc 1 để làm VD: Số lượng các số chia hết cho 2 (<= N) là: [N/2] (trong đó [] là chia lấy nguyên). Số lượng các số chia hết cho 3 (<= N) là: [N/3] (trong đó [] là chia lấy nguyên). Số lượng các số chia hết cho cả 2 và 3 (<= N) là: [N/6] (trong đó [] là chia lấy nguyên). -> Số lượng các số không chia chia hết cho 2 và 3 (<= N) là: N - ([N/2] + [N/3] - [N/6]) (trong đó [] là chia lấy nguyên). Tổng quát: Với 5 số A, B, C, D, E thì: ta có đáp án: = N - ([N/A]+[N/B]+..+[N/E] -[N/(A*B)]-[N/(A*C)]-...-N[N/(D*E)] +[N/(A*B*C)]+[N/(A*B*D)]+...+[N/(C*D*E)]) -[N/(A*B*C*D)]-...-[N/(B*C*D*E)] +[N/(A*B*C*D*E)]) Ví dụ cho 3 số A=2 B=3 C=5, biểu diễn các số chia hết cho A, B, C theo dạng tập hợp;
Ta thấy S(A+B+C) là tập những số chia hết cho 2 hoặc 3 hoặc 5 = S(A) + S(B) + S(C) - S(A.B) - S(B.C) - S(C.A) + S(A.B.C)
trong đó S (x) là tập các số chia hết cho x. 
Việc cần làm giờ là chỉ cần sinh nhị phân chọn các cặp số và tính toán số lượng các số của các cặp tích số.

  • Code:

C++:



JAVA:


BCTEST13 - Tổng may mắn

BCTEST13 - Tổng may mắn

Link Sub: http://www.spoj.com/PTIT/problems/BCTEST13/
Người Gửi: Dương Lee

  • Problem:

Cùng sở thích với Bờm, Tèo cũng rất thích các số may mắn. Ta đã biết rằng một số gọi là số may mắn nếu biểu diễn thập phân của nó chỉ chứa các chữ số may mắn là 4 và 7. Ví dụ: Các số 47,744,4 là số may mắn còn 5,17,467 không phải là số may mắn.  
Nhưng khác với Bờm, Tèo lại định nghĩa next(x) là số may mắn bé nhất lớn hơn hoặc bằng x.  
Mở rộng hơn nữa, Tèo lại nghĩ ra Tổng may mắn LKSUM của hai số l,r (l≤r) như sau:  
LKSUM=next(l)+next(l+1)+...+next(r-1)+next(r)  
Bài toán đã trở nên khó khăn hơn nên Tèo cần sự giúp đỡ của các bạn sinh viên PTIT. Hãy giúp Tèo bài toán trên nhé !!!

Input
Một dòng duy nhất chứa hai số nguyên l và r (1≤l≤r≤109).
Output
Một số nguyên duy nhất là giá trị của tổng LKSUM.
Example:
Input
2 7
Output:
33

Giải thích: next(2)+next(3)+next(4)+next(5)+next(6)+next(7)=4+4+4+7+7+7=33
Input
7 7
Output:
7
Giải thích: next(7)=7
  • Solution:

- Cách làm: + Sinh các trường hợp từ 1->10 chữ số cho 4 và 7; Sau khi sinh sẽ có mảng dãy số v[]={ 4, 7, 44, 47, ..., 77..7 } được đánh số thứ tự từ 0, 1, 2, 3, ...., size(). + Chặt nhị phân tìm số lớn hơn gần với nó nhất trong mảng v. (p/s vì sinh tối đa 10 chữ số nên độ phức tạp cũng không nhiều khoảng O(10000) nên có thể dùng tìm kiếm tuyến tính). + Xét các trường hợp và tính toán các khoảng tạo ra. VD: 2 và 8 -> tìm được: 4 và 44 -> tạo ra các khoảng: (2, 4] gồm các số có next()=4; (4, 7] gồm các số có next()=7; (7, 8] gồm các số có next()=44; Như vậy chỉ cần biết được các khoảng chia sẽ biết được có bao nhiêu số trong đó có cùng giá trị next.

  • Code:

C++:



JAVA:


DTTUI1 - Cái túi 1

DTTUI1 - Cái túi 1

Link Sub: http://vn.spoj.com/problems/DTTUI1/
Người Gửi: Dương Lee

  • Problem:

Cây khế nhà Khánh rất sai quả nên có một con chim to to đến ăn. Ăn xong, chim chở Khánh ra đảo để trả công bằng vàng. Đảo có N cục vàng. Anh ấy muốn chuyển hết cả N cục vàng của mình về nhà. Nhưng khổ nổi các cục vàng này lại có trọng lượng và kích thước khổng lồ. Khánh đem theo một cái túi ba trăm gang to đùng nhưng vẫn chưa chắc chứa hết đống vàng này. Khổ quá đi! Lấy cục nào, bỏ cục nào bây giờ! Các bạn giúp anh ấy tìm ra một cách chọn vàng để thu được giá trị lớn nhất mà vẫn không làm rách túi đi.
Input
Dòng 1: Chứa 2 số nguyên: số cục vàng N (1 ≤ N ≤ 40) và tải trọng tối đa của túi M (1 ≤ M ≤ 10^9). 
N dòng sau: Mỗi dòng chứa 2 số nguyên: trọng lượng Wi và giá trị Vi của cục vàng thứ i (1 ≤ Wi, Vi ≤ 10^8).
Output
Một số nguyên duy nhất là giá trị lớn nhất thu được.
Example:
Input
3 4
1 4
2 5
3 6
Output:
10

  • Solution:

Bài này N=40 (không quá lớn) nên ta có thể phân tập. Các bước làm: - Chia đôi tập dữ liệu nhận vào: P2: N2=N/2 và P1: N1=N-(N/2); - Sinh nhị phân các trường hợp chọn vàng của P1 và P2 (sao cho khối lượng không quá M ở mỗi tập + nhánh cận để giảm time). - Sắp xếp P2 tăng dần theo khối lượng. - Quy hoạch lại giá trị của mỗi cục vàng (S[]) sao cho S[i] = max (P2_[1->i]_V). - Với mỗi W của P1_i tìm vị trí (VT) P2 có W sao cho (P2_W + P1_i_W <= M). (Tìm nhị phân). - Với mỗi VT ta đã có sẵn S[VT] là giá trị max V của P2 đã quy hoạch ngay trên. Chỉ cần lấy Ans = max (Ans, P1_i_V+S[VT]). *Chú ý: Vì mỗi P1_W và P2_W nó đã <= M rồi nên cũng cần so sánh Ans với P1_V, P2_V;

  • Code:

C++:



JAVA:


PTIT124B - Giải mã bằng ma trận xoáy ốc

PTIT124B - Giải mã bằng ma trận xoáy ốc

Link Sub: http://www.spoj.com/PTIT/problems/PTIT124B/
Người Gửi: Dương Lee

  • Problem:

Chip và dale đã phát minh ra một phương pháp mã hóa để che giấu các tin nhắn văn bản. Đầu tiên chúng sử dụng 2 số là số hàng (R) và số cột (C) của ma trận. Người gửi sẽ mã hóa theo quy tắc sau:

- Văn bản gồm các chữ cái in hoa [A-Z] và dấu cách

- Mỗi kí tự sẽ có một giá trị thập phân như sau:

Dấu cách = 0, A=1, B=2, ..., Y=25, Z=26

Người gửi lấy 5 kí tự nhị phân đại diện cho giá trị chữ cái tương ứng và điền vào ma trận theo hình xoáy ốc như hình dưới. Ma trận sẽ được điền thêm các số 0 nếu còn thiếu. Ví dụ: nếu văn bản mã hóa là “ACM” và R=4 và C=4, ma trận sẽ được điền như sau:

0→0→0→0 
      ↓
1→1→0 1
↑   ↓ ↓
0 0←1 0
↑     ↓
1←1←0←0

A = 00001, C = 00011, M = 01101

(1 chữ số 0 được thêm vào để lấp đầy ma trận)

Các bit trong ma trận sau đó được nối với nhau theo hàng và gửi đến người nhận

Ví dụ trên sẽ được mã hóa thành: 0000110100101100
Input
Dòng 1 chứa số nguyên N (1<=N<=1000) là số bộ test.  
Sau đó là N bộ test, mỗi bộ test gồm 1 dòng có dạng như sau: R (1<=R<=20),  dấu cách, C (1<=C<=20), dấu cách, và đoạn văn bản đã được mã hóa. Độ dài của đoạn văn bản đã mã hóa là (R*C).
Output
Với mỗi bộ test, in ra trên 1 dòng chứa: số thứ tự bộ test, dấu cách, và kết quả giải mã. Bạn phải vứt bỏ các dấu cách ở cuối khi giải mã.
Example:
Input
4
4 4 0000110100101100
5 2 0110000010
2 6 010000001001
5 5 0100001000011010110000010
Output:
1 ACM
2 HI
3 HI
4 HI HO

  • Solution:

- Sẽ sinh theo đệ quy các trường bit 0 và 1 -> 00000, 00001, ... - Mỗi trường bit sinh ra sẽ được KH là A, B,... theo thứ tự. VD: ' ': 00000, A: 00001, ... - Đọc dữ liệu đầu vào theo mảng thường. - Đọc dữ liệu theo dạng xoắn ốc và chuyển nó thành xâu 1 chiều. - Đọc 5 kí tự một và tìm trong mảng xem nó trùng với bit nào thì in KH của nó ra.

  • Code:

C++:



JAVA:


P146PROF - ROUND 6F - Tam giác

P146PROF - ROUND 6F - Tam giác

Người Gửi: dfgsdf

  • Problem:

Em gái của Tí rất thông minh và lanh lợi. Khi mới đi học về từ trường mẫu giáo, cô bé khoe với anh trai về các các câu hỏi ở trường. Nhiệm vụ ngày hôm nay là xây dựng một hình tam giác trong số 4 chiếc que khác màu nhau. Đương nhiên là thừa một cây gậy. Không được phép bẻ các que ra và cũng như chỉ sử dụng một phần chiều dài của chúng. Em gái của Tí đã hoàn toàn giải quyết được bài toán của cô giáo, và khi về nhà, cô yêu cầu anh trai làm lại điều đó.  
Tí bảo dễ ợt. Tuy nhiên, sau một thời gian Tí phát hiện ra có một số điều tương đối phức tạp. Có thể không dựng được 1 hình tam giác có diện tích dương, nhưng có thể dựng 1 tam giác suy biến (thành đoạn thẳng). Và thậm chí có trường hợp không thể dựng được tam giác suy biến.  
Tí không muốn xem xét nhiều trường hợp, nên bạn ấy nhờ các bạn giúp đỡ.
Input
Gồm 4 số nguyên dương (<= 100) là độ dài của 4 que.
Output
In ra “TRIANGLE” nếu có thể dựng được 1 tam giác không suy biến.  
In ra “SEGMENT” nếu dựng được 1 tam giác suy biến thành đoạn thẳng.
In ra “IMPOSSIBLE” trong trường hợp còn lại.
Example:
Input
4 2 1 3
Output:
TRIANGLE

Input
7 2 2 4
Output:
SEGMENT
Input
3 5 9 1
Output:
IMPOSSIBLE
  • Solution:

Tam giác suy biến là tam giác có 2 cạnh cộng lại bằng cạnh còn lại. Từ đó cứ sinh tổ hợp các cách lấy các cạnh và dựa theo đề bài mà kiểm tra thôi =)).

  • Code:

C++:



JAVA:


P171SUMA - ROUND 1A - Kiểm tra hình chữ nhật

Người Gửi: Dương Lee

  • Problem:

Trên mặt phẳng cho 4 điểm (2 điểm có thể trùng nhau). Hãy kiểm tra xem 4 điểm đó có thể tạo thành 1 hình chữ nhật có các cạnh song song với các trục toạ độ hay không. Lưu ý 1 điểm hoặc 1 đoạn thẳng không được tính là 1 hình chữ nhật.


Input

Dòng đầu tiên chứa một số nguyên dương n (n <= 1000) là số lượng bộ test.  
Mỗi bộ test gồm 4 dòng, mỗi dòng gồm 1 cặp số x, y là toạ độ của 4 điểm trên mặt phẳng.
Output
In ra n dòng, Mỗi dòng chứa 1 xâu kết quả là "YES" nếu 4 điểm có thể tạo thành 1 hình chữ nhật, hoặc "NO" nếu ngược lại.
Example:
Input
2
-1 2
3 2
3 5
-1 5
2 4
5 6
2 3
1 2
Output:
YES
NO

  • Solution:

- Bài này sinh hoán vị của 4 để tạo ra các trường hợp đặt vị trí cho 4 đỉnh nhập vào. 
- Sinh xong thì chỉ cần xác định lại kiểm tra điều kiện nó là hcn nữa là ok.  
- xem hình ảnh để hiểu rõ hơn:

  • Code:

C++:



JAVA:


P132SUMJ - SUM2 J - Hoán vị chữ số

P132SUMJ - SUM2 J - Hoán vị chữ số

Link Sub: http://www.spoj.com/PTIT/problems/P132SUMJ/
Người Gửi: Sai

  • Problem:

Cho trước một số nguyên dương X. Nhiệm vụ của bạn là tìm số nhỏ nhất lớn hơn X, mà có các chữ số giống hệt với X.

Input
Dòng đầu tiên là số nguyên X (1 ≤ X ≤ 999 999).  
Chữ số đầu tiên của X luôn khác 0.
Output
In ra đáp số trên một dòng. Nếu không có đáp số, in ra “0”.
Example:
Input
156
Output:
165

Input
330
Output:
0
Input
27711
Output:
71127
  • Solution:

Bài này thực chất là sinh hoán vị kế tiếp của một số chủ yếu là các bạn xử lí string. Nhập vào một string và sinh hoán vị cấu hình kế tiếp của nó.

  • Code:

C++:

https://ideone.com/vircn1

#include <iostream>
#include <string>
using namespace std;

int main ()
{
    string n;
    cin>>n;
    int len = n.length();
    int vt=-1;
    for (int i=len-1; i>0; i--)
    {
        int nit1=n[i-1]-'0';
        int ni=n[i]-'0';
        if (nit1<ni)
        {
            vt=i-1;
            break;
        }
    }
    if (vt==-1) cout<<"0";
    else
    {
        for (int i=len-1; i>=0; i--)
        {
            int ni=n[i]-'0';
            int nvt=n[vt]-'0';
            if (ni>nvt)
            {
                int tg=ni;
                n[i]=nvt+'0';
                n[vt]=tg+'0';
                break;
            }
        }
        for (int i=vt+1; i<len; i++)
        {
            for (int j=vt+1; j<len-1; j++)
            {
                int nj=n[j]-'0';
                int njc1=n[j+1]-'0';
                if (nj>njc1)
                {
                    int tg=nj;
                    n[j]=njc1+'0';
                    n[j+1]=tg+'0';
                }
            }
        }
        for (int i=0; i<len; i++) cout<<n[i];
    }
    return 0;
}


JAVA:


PTIT121L - Ghép hình

Link Sub: http://www.spoj.com/PTIT/problems/PTIT121L/
Người Gửi: Dương Lee

  • Problem:

Cho 3 hình chữ nhật có kích thước tương ứng là: a[i]×b[i] (i=1,2,3). Trong đó a[i],b[i] là các số nguyên dương không quá 10^9. Hỏi 3 hình chữ nhật trên có thể ghép thành một hình vuông không? Nếu ghép được cho biết độ dài cạnh hình vuông đó, ngược lại ghi số 0.

Input
Gồm 3 dòng, mỗi dòng ghi 2 số nguyên dương là kích thước của một hình chữ nhật
Output
Một dòng duy nhất là đáp số của bài toán
Example:
Input
1 6
6 2
3 6
Output:
6

Input
1 6
6 2
2 4
Output:
0
  • Solution:

- Sắp xếp từng cặp (các phần tử trong cặp tăng dần): rộng dài - Có hai cách để ghép: C1: 3 cái chồng lên nhau; C2: 2 cái chập lại và ghép với 1 cái còn lại tạo thành 3 phần phân biệt. - C1: thì dễ rồi chỉ cần xét điều kiện sum_Rộng=dài; - C2: ở code này mình dùng sinh hoán vị 3 để sinh các trường hợp đặt hcn đặt vào các vị trí (các bạn có thể dùng if xét các trường hợp). Lưu ý: phải thay đổi dài rộng lẫn nhau cho mỗi hcn để đảm bảo có tất cả trường hợp được sinh. Xem hình ảnh để rõ hơn:


  • Code:

C++:



JAVA: