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;
}
posted @ 2020-09-02 20:43  nonameless  阅读(169)  评论(0编辑  收藏  举报