Hint
- Cách làm giống với sinh xâu nhị phân có độ dài không quá $$$n$$$, điểm khác biệt ở đây là
0
ta sẽ coi là6
, còn1
thì ta coi nó như là8
. - Ta sẽ sử dụng hàng đợi để giải quyết, ban đầu cho
6
và8
bắt đầu chạy, với mỗi xâu ở đầu hàng đợi thì ta sẽ cần kiểm tra nếu nối thêm $$$1$$$ số vào đuôi mà độ dài chưa quá $$$n$$$ thì mới được chấp nhận.
Code (C++)
#include<bits/stdc++.h>
using namespace std;
#define out(x) return cout << x, void()
#define all(x) x.begin(), x.end()
#define len(x) (int)x.size()
#define el '\n'
#define int long long
const int mod = 1e9 + 7;
const int oo = 1e18 + 7;
const int mxn = 1e6 + 7;
void solve(){
int n; cin >> n;
int mx = (int)pow(1ll * 10, n);
vector<int> v;
queue<int> q;
q.push(6);
q.push(8);
while(len(q)){
int x = q.front(); q.pop();
v.push_back(x);
if(x * 10 + 6 < mx){
q.push(x * 10 + 6);
q.push(x * 10 + 8);
}
}
cout << len(v) << el;
for(int &i : v) cout << i << ' ';
cout << el;
}
signed main(){
cin.tie(0) -> sync_with_stdio(0);
int tc = 1; cin >> tc;
while(tc--) solve();
}
Hint
- Vì các toán hạng có thể có nhiều chữ số, hoặc là số âm nên ta sẽ coi mỗi toán tử/toán hạng là một xâu ký tự. Như vậy, ta sẽ nhập vào một mảng gồm $$$n$$$ xâu ký tự, rồi xử lý giống như bài ở trên Code PTIT.
- Ở đây, để kiểm tra một xâu đang duyệt đến có là "số" hay không thì ta chỉ cần kiểm tra ký tự cuối cùng của nó có là chữ số hay không ? Điều này sẽ giúp ta vừa kiểm tra được khi quyết định nhét nó vào stack cũng như là xác định biểu thức là tiền tố hay hậu tố.
Code (C++)
#include<bits/stdc++.h>
using namespace std;
#define out(x) return cout << x, void()
#define all(x) x.begin(), x.end()
#define len(x) (int)x.size()
#define el '\n'
#define int long long
const int mod = 1e9 + 7;
const int oo = 1e18 + 7;
const int mxn = 1e6 + 7;
void solve(){
int n; cin >> n;
string a[n+5];
for(int i=1; i<=n; i++){
cin >> a[i];
}
stack<int> st;
if(isdigit(a[1].back())){
for(int i=1; i<=n; i++){
if(isdigit(a[i].back())){
st.push(stoll(a[i]));
}else{
int x = st.top(); st.pop();
int y = st.top(); st.pop();
if(a[i] == "+"){
st.push(x + y);
}else if(a[i] == "-"){
st.push(y - x);
}else if(a[i] == "*"){
st.push(x * y);
}else{
st.push(y / x);
}
}
}
}else{
for(int i=n; i>=1; i--){
if(isdigit(a[i].back())){
st.push(stoll(a[i]));
}else{
int x = st.top(); st.pop();
int y = st.top(); st.pop();
if(a[i] == "+"){
st.push(x + y);
}else if(a[i] == "-"){
st.push(x - y);
}else if(a[i] == "*"){
st.push(x * y);
}else{
st.push(x / y);
}
}
}
}
cout << st.top() << el;
}
signed main(){
cin.tie(0) -> sync_with_stdio(0);
int tc = 1; cin >> tc;
while(tc--) solve();
}
577502C - BFS trên đồ thị vô hướng
Hint
- Đây là dạng bài BFS cơ bản về việc tìm đường đi giữa $$$2$$$ đỉnh trên đồ thị, ta sẽ duy trì các biến sau đây:
- Hàng đợi: lưu các đỉnh của đồ thị.
- Mảng par: lưu đỉnh liền kề trước của một đỉnh nào đó, phục vụ cho việc truy vết lại đường đi để xác định độ dài.
- Mảng vis: đánh dấu xem đỉnh nào đó đã được thăm hay chưa.
- Sau đó, ta sẽ bắt đầu chạy từ đỉnh $$$s$$$, đến khi nào gặp được đỉnh $$$t$$$ thì break. Cuối cùng, nếu
vis[t] = 1
thì ta sẽ truy vết lại đường đi và in ra kết quả. Ngược lại, ta sẽ in ra-1
.
Code (C++)
#include<bits/stdc++.h>
using namespace std;
#define out(x) return cout << x, void()
#define all(x) x.begin(), x.end()
#define len(x) (int)x.size()
#define el '\n'
#define int long long
const int mod = 1e9 + 7;
const int oo = 1e18 + 7;
const int mxn = 1e3 + 7;
int n, m, s, t;
vector<int> a[mxn];
void solve(){
cin >> n >> m >> s >> t;
while(m--){
int x, y; cin >> x >> y;
a[x].push_back(y);
a[y].push_back(x);
}
int par[n + 1] = {0};
bool vis[n + 1] = {0};
queue<int> q;
q.push(s);
vis[s] = 1;
while(len(q)){
int u = q.front(); q.pop();
if(u == t) break;
for(int &v : a[u]){
if(!vis[v]){
vis[v] = 1;
par[v] = u;
q.push(v);
}
}
}
if(vis[t]){
int res = 0;
while(t != s){
++res;
t = par[t];
}
cout << res << el;
}else cout << "-1\n";
for(int i=1; i<=n; i++) a[i].clear();
}
signed main(){
cin.tie(0) -> sync_with_stdio(0);
int tc = 1; cin >> tc;
while(tc--) solve();
}
577502D - Cây nhị phân tìm kiếm
Hint
- Đây là một bài tập yêu cầu chúng ta phải nắm rõ về thao tác chèn trên cây nhị phân tìm kiếm (BST). Nếu bạn chưa rõ thì thao tác sẽ được chạy như sau:
- Ta gọi node đang xét đến là $$$x$$$, và giá trị $$$a_i$$$ đang cần chèn.
- Nếu $$$a_i < x \to val$$$, thì tức là $$$a_i$$$ cần thuộc cây con bên trái của $$$x$$$, và ta sẽ chạy xuống để tiếp tục chèn.
- Nếu $$$a_i > x \to val$$$, thì tức là $$$a_i$$$ cần thuộc cây con bên phải của $$$x$$$, và ta sẽ chạy xuống để tiếp tục chèn.
- Nếu $$$x$$$ là con trỏ
NULL
, tức là ta đã tìm thấy vị trí cần chèn, ta sẽ tạo cho $$$x$$$ là một node mới với giá trị chính là $$$a_i$$$. - Cuối cùng, ta sẽ duyệt theo phép Post Order để in ra kết quả.
Code (C++)
#include<bits/stdc++.h>
using namespace std;
#define out(x) return cout << x, void()
#define all(x) x.begin(), x.end()
#define len(x) (int)x.size()
#define el '\n'
#define int long long
const int mod = 1e9 + 7;
const int oo = 1e18 + 7;
const int mxn = 1e6 + 7;
struct node{
int val;
node *l, *r;
node(int x){
val = x;
l = r = 0;
}
};
void ins(node *&x, int v){
if(!x){
x = new node(v);
return;
}
if(v < x->val) ins(x->l, v);
else ins(x->r, v);
}
void post(node *x){
if(!x) return;
post(x->l);
post(x->r);
cout << x->val << ' ';
}
int cnt = 1;
void solve(){
cout << "Test #" << cnt++ << ": ";
int n; cin >> n;
int a[n+5];
for(int i=1; i<=n; i++){
cin >> a[i];
}
node *x = nullptr;
for(int i=1; i<=n; i++) ins(x, a[i]);
post(x); cout << el;
}
signed main(){
cin.tie(0) -> sync_with_stdio(0);
int tc = 1; cin >> tc;
while(tc--) solve();
}