Loading

Codeforces Round #708 (Div. 2)

C1-k-LCM (easy version)

分情况讨论一下

void solve(){
    if(n & 1){
        cout << 1 << " " << (n / 2) << " " << (n / 2) << '\n';
    }
    else if(n % 4 == 0){
        cout << (n / 2) << " " << (n / 4) << " " << (n / 4) << '\n';
    }
    else{
        cout << 2 << " " << ((n - 2) / 2) << " " << ((n - 2) / 2) << '\n';
    }
}

C2-k-LCM (hard version)

转化成C1

void solve() {
    for(int i = 1;i <= k - 3;i++){
        cout << 1 << " ";n--;
    }
    if (n & 1) {
        cout << 1 << " " << (n / 2) << " " << (n / 2) << '\n';
    }
    else if (n % 4 == 0) {
        cout << (n / 2) << " " << (n / 4) << " " << (n / 4) << '\n';
    }
    else {
        cout << 2 << " " << ((n - 2) / 2) << " " << ((n - 2) / 2) << '\n';
    }
}

D-Genius

看完官方的题解感觉挺巧妙的, 设 \(f[i]\) 表示以 \(i\) 为终点的最大得分值, 则把边按照从小到大的顺序来枚举,进行转移即可

for(int i = 2;i <= n;i++){
    for(int j = i - 1;j >= 1;j--){
    	
    }
}

这样的枚举顺序可以保证边权 (\(abs(c_i - c_j)\)) 严格递增

void solve() {
    vector<ll>f;
    f.resize(n + 1, 0);
    for (int i = 2;i <= n;i++) {
        for (int j = i - 1;j >= 1;j--) {
            ll fi = f[i], fj = f[j], p = abs(s[i] - s[j]);
            if (tag[i] != tag[j]) {
                f[i] = max(f[i], fj + p);
                f[j] = max(f[j], fi + p);
            }
        }
    }
    cout << *max_element(f.begin(), f.end()) << '\n';
}

E1-Square-free division (easy version)

直接质因数分解然后次数全部模 2 ,转化为分成尽可能少的区间, 使得所有区间内的数两两各不相同,扫一遍就可以

E-2Square-free division (hard version)

\(f[i][j]\) 表示前 \(i\) 个数,使用了 \(j\) 次转变的最小段数, 设 \(L[i][j]\) 表示前 \(i\) 个数中, \(i\) 所属的段使用了 \(j\) 次转变所能到达的最左边的下标, 即 \([L[i][j],\ \ i]\) 这个段使用了 \(j\) 次转变,且无法继续向左延申

处理 \(L\) 的时候可以 \(O(nk)\) 处理出来, 枚举 \(k\) ,然后扫一遍。

转移的时候

for (int i = 1;i <= n;i++) {
        for (int j = 0;j <= k;j++) {
            if (j > 0)f[i][j] = f[i][j - 1];
            for (int lst = 0;lst <= j;lst++) {
                f[i][j] = min(f[i][j], f[L[i][lst] - 1][j - lst] + 1);
            }
        }
    }
#include<bits/stdc++.h>
using namespace std;
#define what(x) cerr << #x << " is " << x << endl;
#define getall(x,ed) cerr << #x << ": \t";debug(x,ed);
#define IO ios::sync_with_stdio(0);cin.tie(0);
std::mt19937 rnd(time(0));
template<typename T>
void debug(T begin, T ed) {
    for (T i = begin;i != ed;i++)cout << *i << '\t';cout << '\n';
}

const int N = 1e7 + 10;
typedef long long ll;

vector<int>prime, vis, fp, A;
void init() {
    vis.resize(N, 0);fp.resize(N, 0);

    for (int i = 2;i < N;i++) {
        if (!vis[i]) {
            prime.emplace_back(i);
            fp[i] = i;
        }
        for (auto& p : prime) {
            if (i * p >= N)break;
            vis[p * i] = 1;
            fp[p * i] = p;
            if (i % p == 0)break;
        }
    }
}

int T, n, k;

void read_and_init() {
    cin >> n >> k;
    A.resize(n + 1, 0);
    for (int i = 1;i <= n;i++) {
        int x;cin >> x;
        A[i] = 1;
        while (x != 1) {
            int p = fp[x];
            x /= p;
            if (fp[x] == p) {
                x /= p;
            }
            else {
                A[i] *= p;
            }
        }
        //cout << A[i] << '\n';
    }
}
unordered_map<int, int>cnt;
void solve() {
    vector<vector<int>>f(n + 1, vector<int>(k + 1, 1e9));
    vector<vector<int>>L(n + 1, vector<int>(k + 1, 0));

    for (int j = 0;j <= k;j++) {
        int now = 0;
        int idx = 1;
        cnt.clear();
        for (int i = 1;i <= n;i++) {

            if (cnt.count(A[i]))now++;
            cnt[A[i]]++;
            //cout << i << " " << now << " " << idx << '\n';
            //for(auto&x : cnt)cout << x.first << " : " << x.second << '\n';
            if (now <= j)L[i][j] = idx;
            else {
                while (idx <= i and now > j) {
                    if (cnt[A[idx]] >= 2)now--;
                    if (!--cnt[A[idx]])cnt.erase(A[idx]);
                    idx++;
                }
                L[i][j] = idx;
            }
            //what(L[i][j]);
        }
    }

    for (auto& c : f[0])c = 0;

    for (int i = 1;i <= n;i++) {
        for (int j = 0;j <= k;j++) {
            if (j > 0)f[i][j] = f[i][j - 1];
            for (int lst = 0;lst <= j;lst++) {
                f[i][j] = min(f[i][j], f[L[i][lst] - 1][j - lst] + 1);
            }
        }
    }
    cout << f[n][k] << '\n';


}
int main() {
    IO;
    init();
    cin >> T;
    while (T--) {
        read_and_init();
        solve();
    }
}
posted @ 2021-03-18 18:05  —O0oO-  阅读(53)  评论(0编辑  收藏  举报