Home Blogs Projects About

Sol 23-11-2021

tags: CTQH

Người chơi thì có thể không thắng. Nhưng người không chơi thì không bao giờ thắng. [name=LamTer]

Weird Algorithm

Bài này có liên quan tới Phỏng đoán Collatz.

Bài này ta cần sử dụng vòng $while$ hoặc sử dụng đệ quy.

Code mẫu của LamTer:

#include <bits/stdc++.h>

using namespace std;

int main() {
    long long int n; cin >> n;
    while(n != 1) {
        cout << n << ' ';
        if(n & 1) n >>=1;
        else n = 3 * n + 1;
    }
    
    cout << 1;
}

Code mẫu của bạn Minh Hiên:

#include <bits/stdc++.h>
using namespace std;
long long int n,i,t;
int main(){
    freopen ("weirdalgorithm.inp","r",stdin);
    freopen ("weirdalgorithm.out","w",stdout);
    cin>>n;
    t=n;
    cout<<n<<" ";
    while (t!=1){
    if (t%2==0) t=t/2;
    else if (t%2!=0) t=(t*3)+1;
    cout<<t<<" ";}
}

Code mẫu của bạn LamTer (sử dụng đệ quy):

#include <bits/stdc++.h>

using namespace std;

void pro(long long int n) {
	cout << n << ' ';
	if(n == 1) exit(0);
	if(n % 2) pro(3 * n + 1);
	else pro(n / 2);
}

int main() {
	int n; cin >> n;
	pro(1LL * n);
}

Missing Number

Đây là một bài khá hay và có nhiều cách làm.

Cách 1: Sắp xếp

Nhận thấy rằng khi ta sắp xếp $n-1$ phần tử đó theo thứ tự bé đến lớn thì:

Tuy nhiên sẽ có một phần tử thứ $i$ mà giá trị của nó là $i + 1$. Thì $i$ chính là số bị mất.

Code mẫu của bạn Hoàng Hải:

#include<bits/stdc++.h>

using namespace std;

const int N = 2e5 + 5;

#define GoldEas "missingnumber"

int main(){
	if(fopen(GoldEas ".inp", "r")){
		freopen(GoldEas ".inp", "r", stdin);
		freopen(GoldEas ".out", "w", stdout);
	}	
	int n, a[N] = {};
	cin >> n;
	for(int i = 1; i < n; i++) cin >> a[i];
	sort(a, a+n);
	for(int i = 1; i < n; i++)
		if(a[i] != i)
		{
			cout << i;
			break;
		}
	return 0;  
}

Cách 2: Dùng hiệu

Ta nhận thấy là nếu lấy tổng từ $1$ đến $n$ trừ cho tổng tất cả các phần tử trong dãy thì sẽ tìm được phần tử còn thiếu.

Code mẫu của bạn Thảo Linh:

#include <bits/stdc++.h>

using namespace std;

int main() {
    int n, e, s_1=0, s_2=0;
    freopen("missingnumber.inp","r",stdin);
    freopen("missingnumber.out","w",stdout);
    vector<int> a;
    cin >> n;
    while (cin>>e) {
        a.push_back(e);
        s_1+=e;
    }
    for (int i=1; i<=n; i++) {
        s_2+=i;
    }
    cout << s_2-s_1 << "\n";

}

Cách 3: Dùng phép toán $xor$

Ta nhận thấy rằng $a \oplus a = 0$.

Ví dụ: \((a \oplus b \oplus c) \oplus (a \oplus b) = (a \oplus a) \oplus (b \oplus b) \oplus c=c\)

Ở đây có thể hiêu $a,b,c$ là dãy gốc $a,b$ là dãy nhập vào còn $c$ là số mất tính. Thì ta thấy chỉ cần $xor$ là tìm được $c$.

Dựa vào tính chất này ta có thể tìm số bị mất bằng cách: \((1 \oplus 2 \oplus 3 \oplus \ldots \oplus n) \oplus (a_1 \oplus a_2 \oplus a_3 \oplus \ldots \oplus a_{n-1}) = the \ missing \ number\)

Code mẫu của bạn LamTer:

#include <bits/stdc++.h>

using namespace std;

int main() {
	int n; cin >> n;
	int xorsum = n;

	for(int i = 1; i < n; i++) {
		int x; cin >> x;
		xorsum ^= x;
		xorsum ^= i;
	}

	cout << xorsum;
}

Repetitions

Code mẫu của LamTer:

#include <bits/stdc++.h>

using namespace std;

int main() {
    string s; cin >> s; s += '#';

    int ans = 1;
    //cur là biến lưu độ dài của chữ cái hiện tại đang xét
    for(int i = 1, cur = 1; i < (int) s.size(); i++) {
        //Nếu thứ i giống chữ thứ i giống chữ trước đó 
        //thì tăng độ dài hiện tại đang xét lên 1
        if(s[i] == s[i - 1]) cur++;
        else {
            //Nếu không thì chúng ta sẽ cập nhật chiều dài tối đa
            ans = max(ans, cur);
            //Và trả độ dài về 1
            cur = 1;
        }
    }
    
    //In ra đáp án
    cout << ans;
}

Increasing Array

Gọi mảng là $a$. Chi phí chuyển đổi là $cost$

Với mỗi $2 \leq i \leq n$ thì ta sẽ xem nếu $a_i < a_{i-1}$ thì ta sẽ tăng $a_i=a_{i-1}$ và cộng chi phí chuyển đổi $cost$ cho $a_{i-1}-a_i$.

Code mẫu của bạn LamTer:

#include <bits/stdc++.h>

using namespace std;

using lli = long long;

int main() {
    lli n;
    cin >> n;
    vector<lli> num;
    for(int i = 1; i <= n; i++) {
        lli temp;
        cin >> temp;
        num.push_back(temp);
    }

    lli ans = 0;
    for(int i = 1; i < n; i++) {
        if(num[i-1] > num[i]) {
            ans += num[i-1] - num[i];
            num[i] = num[i - 1];
        }
    }

    cout << ans;

    return 0;
}

Code mẫu của Thảo Linh:

#include<bits/stdc++.h>
#define ll long long
using namespace std;

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    vector<ll int> a;
    ll int n, s = 0;
    freopen("increasingarray.inp","r",stdin);
    freopen("increasingarray.out","w",stdout);
    cin >> n;
    a.resize(n);
    for (auto &i : a) cin >> i;
    for (ll int i = 1; i<n; i++) {
        if (a[i]<a[i-1]) {
            ll int p = a[i-1]-a[i];
            s+=p;
            a[i]+=p;
        }
    }
    cout << s;
    return 0;
}

Có thể bạn chưa biết $2 - 1 = 0!$ [name=LamTer]