Codeforces Round #694 (Div. 2)

Codeforces Round #694 (Div. 2)

熬夜逆向上分

A. Strange Partition

\(\lceil \frac{a+b}{x} \rceil <= \lceil \frac{a}{x} \rceil + \lceil \frac{b}{x} \rceil\)

所以最大的时候肯定是初始状态,最小的时候肯定是全加起来的时候。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
 
 
int main() {
    int t;
    scanf("%d", &t);
    while(t--) {
        int n, x;
        scanf("%d%d", &n, &x);
        LL max_num = 0, min_num = 0;
        for (int i = 1; i <= n; i++) {
            int p;
            scanf("%d", &p);
            max_num += p / x + (p % x != 0);
            min_num += p;
        }
        min_num = min_num / x + (min_num % x != 0);
        printf("%lld %lld\n", min_num, max_num);
    }
}

B. Strange List

一个数被拆掉,拆出来的数字之和(贡献)还是等于这个数。

如果把一个数拆出来的数叫做 衍生数,那就看哪个数的衍生数先拆不掉就好了。

能拆掉就把这个衍生数对应的初始数加入答案,不能拆掉就结束程序。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAXN = 1e5 + 10;
 
int a[MAXN], b[MAXN];
int n, x;
 
LL get_ans() {
    LL ans = 0;
    for (int i = 1; i <= n; i++) {
        ans += a[i];
    }
    while(true) {
        for (int i = 1; i <= n; i++) {
            if (b[i] % x == 0) {
                ans += a[i];
                b[i] /= x;
            } else {
                return ans;
            }
        }
    }
}
 
int main() {
    int t;
    scanf("%d", &t);
    while(t--) {
        scanf("%d%d", &n, &x);
        for (int i = 1; i <= n; i++) {
            scanf("%d", &a[i]);
            b[i] = a[i];
        }
        printf("%lld\n", get_ans());
    }
}

C. Strange Birthday Party

因为可以用钱招待(打发)客人,所以把客人按照钱从大到小排序,能给玩具就给玩具,不能给的用钱招待(打发)

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAXN = 3e5 + 10;
 
int a[MAXN], p[MAXN];
 
bool cmp(int x, int y) {
    return p[x] > p[y];
}
 
int main() {
    int t;
    scanf("%d", &t);
    while(t--) {
        int n, m;
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= n; i++) {
            scanf("%d", &a[i]);
        }
        for (int i = 1; i <= m; i++) {
            scanf("%d", &p[i]);
        }
        sort(a+1, a+1+n);
        reverse(a+1, a+1+n);
 
        int tag = 1;
        LL ans = 0;
        for (int i = 1; i <= n; i++) {
            if (tag < a[i]) {
                ans += p[tag++];
            } else {
                ans += p[a[i]];
            }
        }
 
        printf("%lld\n", ans);
    }
}

D. Strange Definition

\(\frac{lcm(x, y)}{gcd(x, y)} = x×y\)

\(\Rightarrow\)所以原题的两数adjacent就是俩数相乘为完全平方数

\(\Rightarrow\)所以就是两个数分解质因数后,每个质因子个数的奇偶性相同

\(\Rightarrow\)若把质因子的奇数个变为1个,偶数个变为0个,(如2^2 * 3^3 \(\Rightarrow\) 3^1,即把每个数都化简成每个素因子最多出现一次的数),那么判断两数是否相乘为完全平方数就变成了判断两数是否相同。

\(1\)时刻,按照题目中的操作,即每个数和除了他自身以外所有相同的数相乘之后,再按照上面化简,会变为1(偶数个相同的,包括自身)或保持不变(奇数个相同的,包括自身)。

\(2\)时刻及以后,数组不再变化。(因为奇数个相同的永远是奇数个,偶数个的都变成了1,1不会再变了)。

所以答案只有第\(0\)时刻和第\(1\)时刻两种。

分解质因数并化简后,统计所有数的出现次数,最大出现次数即是\(ans0\)

对于除了\(1\)的出现次数以外,数值为偶数的出现次数求和,再加上\(1\)的出现次数,记为\(ans\),则\(ans1=max(ans0, ans)\)

因为一直TLE,以上想法不保证正确,以下代码为TLE代码。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAXN = 3e5 + 10;
const int MAX_NUM = 1e6 + 10;

int pre_solve(int x) {
    int ans = 1;
    for (int i = 2; i <= x; i++) {
        if (x % i == 0) {
            int cnt = 0;
            while(x % i == 0) {
                x /= i;
                cnt++;
            }
            if (cnt % 2 == 1) {
                ans *= i;
            }
        }
    }
    return ans * x;
}

int a[MAXN];
unordered_map<int, int> count_m;

int main() {
    int t, n, q;
    scanf("%d", &t);
    while(t--) {
        scanf("%d", &n);
        count_m.clear();

        for (int i = 1; i <= n; i++) {
            scanf("%d", &a[i]);
            a[i] = pre_solve(a[i]);
            count_m[a[i]]++;
        }

        int w0 = 0, w1 = count_m[1];
        for (auto it : count_m) {
            w0 = max(w0, it.second);
            if (it.second % 2 == 0 && it.first != 1) {
                w1 += it.second;
            }
        }

        scanf("%d", &q);
        LL w;
        for (int i = 1; i <= q; i++) {
            scanf("%lld", &w);
            if (w == 0) {
                printf("%d\n", w0);
            } else {
                printf("%d\n", max(w0, w1));
            }
        }
    }
}

睡觉觉~


找到TLE的原因了,pre写挫了。
AC代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAXN = 3e5 + 10;
const int MAX_NUM = 1e6 + 10;

int pre_solve(int x) {
    for (int i = 2; i*i <= x; i++) {
        while(x % (i*i) == 0) {
            x /= i*i;
        }
    }
    return x;
}

int a[MAXN];
unordered_map<int, int> count_m;

int main() {
    int t, n, q;
    scanf("%d", &t);
    while(t--) {
        scanf("%d", &n);
        count_m.clear();

        for (int i = 1; i <= n; i++) {
            scanf("%d", &a[i]);
            a[i] = pre_solve(a[i]);
            count_m[a[i]]++;
        }

        int w0 = 0, w1 = count_m[1];
        for (auto it : count_m) {
            w0 = max(w0, it.second);
            if (it.second % 2 == 0 && it.first != 1) {
                w1 += it.second;
            }
        }

        scanf("%d", &q);
        LL w;
        for (int i = 1; i <= q; i++) {
            scanf("%lld", &w);
            if (w == 0) {
                printf("%d\n", w0);
            } else {
                printf("%d\n", max(w0, w1));
            }
        }
    }
}

posted @ 2021-01-06 01:15  jvruodejrLS  阅读(102)  评论(0编辑  收藏  举报

Contact with me