1. 程式人生 > 實用技巧 >Codeforces #666 div2 A - D 解題報告

Codeforces #666 div2 A - D 解題報告

題目連結


A. Juggling Letters

題意:

給定 \(n\) 個字串,可以任意改變字元的位置(從一個字串插入到另一個字串的任意位置),問能否將 \(n\) 個字串變得一樣?

思路:

統計每個字元出現的次數,如果是 \(n\) 的倍數,那麼就可以均分,否則不行。

程式碼:
/*
 * @Author       : nonameless
 * @Date         : 2020-09-02 15:08:08
 * @LastEditors  : nonameless
 * @LastEditTime : 2020-09-02 15:16:36
 */
#include <bits/stdc++.h>
#define x first
#define y second
#define pb push_back
#define sz(x) (int)x.size()
#define all(x) x.begin(), x.end()
using namespace std;
typedef long long ll;
typedef pair<ll, ll> PLL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
const double eps = 1e-6;
const double PI  = acos(-1.0);
const int INF = 0x3f3f3f3f;
const ll LNF  = 0x3f3f3f3f3f3f;
inline int gcd(int a, int b) { return b ? gcd(b, a % b) : a; }
inline ll  gcd(ll  a, ll  b) { return b ? gcd(b, a % b) : a; }
inline int lcm(int a, int b) { return a * b / gcd(a, b); }

int cnt[30];
char s[1010];

int main(){

    int t;
    scanf("%d", &t);
    while(t --){
        memset(cnt, 0, sizeof cnt);
        int n; scanf("%d", &n);
        for(int i = 1; i <= n; i ++){
            scanf("%s", s + 1);
            int len = strlen(s + 1);
            for(int j = 1; j <= len; j ++) cnt[s[j] - 'a'] ++;
        }
        int mark = 1;
        for(int i = 0; i < 26; i ++)
            if(cnt[i] % n){
                mark = 0;
                break;
            }
        if(mark) puts("Yes");
        else puts("No");
    }
    return 0;
}


B. Power Sequence

題意:

給定一個整數的數列。你可以通過以下兩種操作來使其變成一個等比數列(以1為首項)

  • 可以任意交換兩個數的位置
  • 花費1的代價使 \(a_i\) 變為 \(a_i + 1\)\(a_i - 1\)

問最小代價可以是多少?

思路:

列舉公差 \(q\)

程式碼:
/*
 * @Author       : nonameless
 * @Date         : 2020-09-02 15:43:08
 * @LastEditors  : nonameless
 * @LastEditTime : 2020-09-02 16:26:15
 */
#include <bits/stdc++.h>
#define x first
#define y second
#define pb push_back
#define sz(x) (int)x.size()
#define all(x) x.begin(), x.end()
using namespace std;
typedef long long ll;
typedef pair<ll, ll> PLL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
const double eps = 1e-6;
const double PI  = acos(-1.0);
const int INF = 0x3f3f3f3f;
const ll LNF  = 0x3f3f3f3f3f3f;
inline int gcd(int a, int b) { return b ? gcd(b, a % b) : a; }
inline ll  gcd(ll  a, ll  b) { return b ? gcd(b, a % b) : a; }
inline int lcm(int a, int b) { return a * b / gcd(a, b); }

const int N = 1e5 + 10;

int a[N];

int main(){

    int n; scanf("%d", &n);
    for(int i = 1; i <= n; i ++) scanf("%d", a + i);
    sort(a + 1, a + n + 1);
    long long ans = LNF;
    for(int c = 1; ; c ++){
        long long tmp = 0;
        long long  s  = 1;
        for(int i = 1; i <= n; i ++){
            tmp += abs(a[i] - s);
            s *= c;
            if(s > 1e14) { tmp += ans; break; }
        }
        if(tmp > ans) break;
        ans = tmp;
    }
    cout << ans << endl;
    return 0;
}


C. Multiples of Length

題意:

給定一個整數陣列,你要做三次操作使得陣列中的每個數都為零。

  • 選定一段連續區間,設 $len = $ 區間長度,你可以使區間中的每個數都加上 \(len\) 的整數倍(包括負數)。
思路:

要在三次操作中解決,那麼顯然我們在兩次操作中要將區間 \([1, n]\) 的數都變為 \(n\) 的整數倍(第三次就可以完成要求),單獨對某個數來看有:\(a_i = a_i + k\times len\)

要將 \(a_i\) 變為 \(n\) 的整數倍,顯然上式就應該出現 \(n\),那麼我們就必須考慮消去 \(a_i\),觀察可以發現當 \(len = n - 1, k = a_i\)

時,可以滿足上述要求。此時 \(a_i = a_i\times n\)

  • 第一次操作區間為 \([1, n - 1]\),每個數加上 \(a_i\times(n- 1)\)
  • 第二次操作將 \(a_n\) 變為 0。
  • 第三次操作區間為 \([1, n]\)
程式碼:
/*
 * @Author       : nonameless
 * @Date         : 2020-09-02 18:50:52
 * @LastEditors  : nonameless
 * @LastEditTime : 2020-09-02 19:00:13
 */
#include <bits/stdc++.h>
#define x first
#define y second
#define pb push_back
#define sz(x) (int)x.size()
#define all(x) x.begin(), x.end()
using namespace std;
typedef long long ll;
typedef pair<ll, ll> PLL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
const double eps = 1e-6;
const double PI  = acos(-1.0);
const int INF = 0x3f3f3f3f;
const ll LNF  = 0x3f3f3f3f3f3f;
inline int gcd(int a, int b) { return b ? gcd(b, a % b) : a; }
inline ll  gcd(ll  a, ll  b) { return b ? gcd(b, a % b) : a; }
inline int lcm(int a, int b) { return a * b / gcd(a, b); }

const int N = 1e5 + 10;

int a[N];

int main(){

    int n; scanf("%d", &n);
    for(int i = 1; i <= n; i ++) scanf("%d", a + i);
    if(n == 1){
        printf("1 1\n%d\n1 1\n0\n1 1\n0\n", -a[1]);
        return 0;
    }
    printf("1 %d\n", n - 1);
    for(int i = 1; i < n; i ++) printf("%lld ", 1ll * a[i] * (n - 1));
    puts("");
    printf("%d %d\n", n, n);
    printf("%d\n", -a[n]);
    printf("1 %d\n", n);
    for(int i = 1; i < n; i ++) printf("%lld ", -1ll * a[i] * n);
    puts("0");

    return 0;
}


D. Stoned Game

題意:

\(n\) 堆石子,兩個人輪流每次取一顆,要求不能從上個人取的那堆裡取,取不到石子的人失敗,問在最優策略下,誰會獲勝?

思路:
  • 考慮一種特殊情況,有一堆石子比其他堆加起來還多,那麼第一個取的人獲勝。
  • 其他情況在最優策略下,肯定會取完所有的石子,那麼根據石子總數的奇偶就可以判斷,奇數先手贏,偶數後手贏。
程式碼:
/*
 * @Author       : nonameless
 * @Date         : 2020-09-02 19:22:54
 * @LastEditors  : nonameless
 * @LastEditTime : 2020-09-02 19:24:45
 */
#include <bits/stdc++.h>
#define x first
#define y second
#define pb push_back
#define sz(x) (int)x.size()
#define all(x) x.begin(), x.end()
using namespace std;
typedef long long ll;
typedef pair<ll, ll> PLL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
const double eps = 1e-6;
const double PI  = acos(-1.0);
const int INF = 0x3f3f3f3f;
const ll LNF  = 0x3f3f3f3f3f3f;
inline int gcd(int a, int b) { return b ? gcd(b, a % b) : a; }
inline ll  gcd(ll  a, ll  b) { return b ? gcd(b, a % b) : a; }
inline int lcm(int a, int b) { return a * b / gcd(a, b); }


int main(){

    int t; scanf("%d", &t);
    while(t --){
        int n; scanf("%d", &n);
        int mx = 0, sum = 0;
        for(int i = 1; i <= n; i ++){
            int x; scanf("%d", &x);
            mx = max(mx, x);
            sum += x;
        }
        if(mx > sum - mx || sum & 1) puts("T");
        else puts("HL");
    }
    return 0;
}