Lời Giải HSG Tin Tỉnh Quảng Ninh (B) - 2019
Bài 1. Tổng các ước
Có hai số nguyên dương .
Yêu cầu
Bạn hãy viết chương trình tính tổng các ước nguyên dương của từng số và tìm tổng lớn hơn trong hai tổng đó, nếu hai tổng có giá trị bằng nhau thì tổng lớn hơn là giá trị bằng nhau đó.
Dữ liệu
Vào từ tệp TONGUOC.INP gồm một dòng ghi hai số nguyên dương viết cách nhau một dấu cách .
Kết quả
Ghi vào tệp TONGUOC.OUT trên một dòng, một số nguyên dương theo yêu cầu bài toán.
Ví dụ
| TONGUOC.INP | TONGUOC.OUT |
|---|---|
| 10 11 | 18 |
| 12 12 | 28 |
Ràng buộc
- số test ứng với số điểm của bài có: .
- số test ứng với số điểm của bài có: .
- số test ứng với số điểm của bài có: .
Lời giải
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define nl '\n'
ll sumdiv(ll n){
if (n==1) return 1;
ll ans = 1 + n;
for (ll i=2;i*i<=n;i++){
if (n%i==0){
if (i*i==n) ans += i ;
else ans += i + n/i;
}
}
return ans;
}
int main()
{
ll x, y;
cin >> x >> y;
cout << max(sumdiv(x), sumdiv(y));
return 0;
}Bài 2. Xâu
Cho số nguyên dương và xâu gồm các kí tự là chữ cái viết liền nhau.
Chuẩn hoá xâu bằng cách chuyển các kí tự chữ cái thường thành các kí tự chữ cái in hoa. Ta quy ước kí tự xuất hiện đầu tiên trong xâu có giá trị là , kí tự tiếp theo xuất hiện trong xâu có giá trị là 2, kí tự tiếp theo xuất hiện trong xâu có giá trị là 3, cứ như thế cho đến cuối xâu . Đối với các kí tự khác cũng quy ước tương tự.
Sau đó tính tổng các giá trị đã được quy ước của xâu .
Ví dụ: nếu thì chuẩn hoá và quy ước:
- Kí tự xuất hiện lần nên có các giá trị lần lượt là .
- Kí tự xuất hiện lần nên có các giá trị lần lượt là .
- Kí tự xuất hiện lần nên có các giá trị lần lượt là .
⇒ Tổng các giá trị xuất hiện sẽ là .
Yêu cầu
Hãy viết chương trình cho biết tổng các giá trị theo quy ước như trên có chia hết cho số nguyên dương hay không. Nếu chia hết thì ghi ra tổng đó, nếu không chia hết thì ghi ra số lượng các chữ cái khác nhau của xâu sau khi chuẩn hoá.
Dữ liệu
Vào từ tệp XAU.INP gồm 2 dòng:
- Dòng 1 chứa số nguyên dương .
- Dòng 2 chứa xâu (không quá kí tự).
Kết quả
Ghi ra tệp XAU.OUT trên một dòng, một số tự nhiên thoả mãn yêu cầu của bài toán.
Ví dụ
| XAU.INP | XAU.OUT | Giải thích kết quả |
|---|---|---|
| 5 AbaCcA | 10 | Sau khi chuẩn hoá, tổng theo quy ước là 10 và chia hết cho 5. Ghi ra 10. |
| 6 gZtAgG | 4 | Sau khi chuẩn hoá, tổng theo quy ước là 9 và không chia hết cho 6. Ghi ra 4 là số kí tự chữ cái khác nhau của xâu S. |
Ràng buộc
- Có số test ứng với số điểm của bài với xâu chỉ xuất hiện ít nhất trong một các kí tự hoặc và độ dài xâu tối đa là kí tự.
- Có số test ứng với điểm của bài với xâu có độ dài tối đa kí tự.
- Có số test ứng với điểm của bài với xâu có độ dài tối đa kí tự.
Lời giải
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define nl '\n'
int main()
{
ll n, ans = 0; cin >> n;
string s; cin >> s;
map<char,int> mp;
for (auto i : s){
if ('a' <= i && i <= 'z'){
ans += ++mp[i-'a'];
}
else{
ans += ++mp[i-'A'];
}
}
if (ans%n==0) cout << ans;
else cout << mp.size();
return 0;
}Bài 3. Dãy số
Cho dãy số có số nguyên . Một dãy con liên tiếp các số hạng của dãy là dãy các số hạng tử số hạng đến số hạng .
Yêu cầu
Hãy cho biết dãy có bao nhiêu dãy con liên tiếp mà giá trị tuyệt đối của tổng các số hạng trong dãy con đó lớn hơn một số nguyên dương cho trước.
Dữ liệu
Vào từ tệp DAYSO.INP gồm 2 dòng:
- Dòng thứ nhất chứa hai số nguyên và .
- Dòng thứ hai chứa số nguyên .
Các số trên cùng một dòng được ghi cách nhau ít nhất một dấu cách.
Kết quả
Ghi ra tệp DAYSO.OUT trên một dòng, một số nguyên duy nhất là số dãy con liên tiếp thoả mãn yêu cầu của bài toán.
Ví dụ
| DAYSO.INP | DAYSO.OUT | Giải thích kết quả |
|---|---|---|
| 5 10 -5 5 6 2 6 | 5 | Các dãy con liên tiếp có giá trị tuyệt đối của tổng lớn hơn 10 là: {5,6}, {5,6,2}, {5,6,2,6}, {-5,5,6,2,6}. |
| 4 4 5 -1 8 -5 | 6 | Các dãy con liên tiếp có giá trị tuyệt đối của tổng lớn hơn 4 là: {5}, {8}, {-1,8}, {5,-1,8}, {5,-1,8,5}. |
Ràng buộc
- Có số test ứng với số điểm của bài có .
- Có số test ứng với số điểm của bài có .
- Có số test ứng với số điểm của bài có .
Lời giải
Ta sử dụng mảng cộng dồng , với là tổng cộng dồn từ đầu mảng đến vị trí .
⇒ Tổng phần tử từ sẽ là .
Theo yêu cầu của bài, cần tìm số đoạn sao cho:
Tương đương với 1 trong 2 trường hợp sau:
- .
- Hoặc .
Giả sử ta có vị trí và sao cho .
- Nếu (tổng tuyệt đối của đoạn là ) và:
- Nếu thì .
- Nếu thì .
- Tương tự, nếu (tổng tuyệt đối của đoạn là ) và:
- Nếu thì .
- Nếu thì .
Ta nhận thấy rằng ở trước hay ở trước đều không quan trọng.
Nghĩa là với mỗi bất kỳ, ta chỉ cần tìm sao cho . Cũng như với mỗi bất kỳ, ta chỉ cần tìm sao cho với .
Từ đó, ta sẽ có ý tưởng sắp xếp mảng theo thứ tự không giảm.
Đến đây, với mỗi vị trí , ta tìm phần tử đầu tiên mà , dẫn đến là các phần tử ở sau cũng sẽ . Vậy ta có được số vị trí tương từng với từng vị trí .
Độ phức tạp: .
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define nl '\n'
int main()
{
int n; cin >> n;
ll s; cin >> s;
ll pref[n+1], ans = 0;
pref[0] = 0;
for (int i=1;i<=n;i++){
ll a; cin >> a;
pref[i] = pref[i-1] + a;
}
sort(pref, pref + n + 1);
for (int i=0;i<=n;i++){
ans += n-(upper_bound(pref, pref + n + 1, pref[i] + s)-pref)+1;
}
cout << ans;
return 0;
}