Codeforces 922F Divisibility 构造

Divisibility

我们考虑删数字

首先我们可以发现有一类数很特殊就是大于 n / 2的素数, 因为这些素数的贡献只有1, 并且在n大的时候,

这些素数的个数不是很少, 我们可以最后用这些数去调整, 并且删掉一个数的时候删掉的是它的因子个数,

所以可以用素数去控制最后的数量。当n小的时候直接状压枚举。

#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define PLL pair<LL, LL>
#define PLI pair<LL, int>
#define PII pair<int, int>
#define SZ(x) ((int)x.size())
#define ull unsigned long long

using namespace std;

const int N = 1e6 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-9;
const double PI = acos(-1);

int n;
LL k;
int rel[N];
bool vis[N];
int now;
vector<int> vc;
set<int> Set;
vector<int> fac[N];

int main() {
    scanf("%d%lld", &n, &k);
    if(n <= 16) {
        vector<int> ret;
        for(int S = 1; S < (1 << n); S++) {
            ret.clear();
            for(int i = 0; i < n; i++)
                if(S >> i & 1) ret.push_back(i + 1);
            int cnt = 0;
            for(int i = 0; i < SZ(ret); i++) {
                for(int j = i + 1; j < SZ(ret); j++) {
                    if(ret[j] % ret[i] == 0) {
                        cnt++;
                    }
                }
            }
            if(cnt == k) {
                puts("Yes");
                printf("%d\n", SZ(ret));
                for(auto& t : ret) printf("%d ", t);
                puts("");
                return 0;
            }
        }
        puts("No");
    } else {
        for(int i = 2; i <= n; i++) {
            for(int j = i + i; j <= n; j += i)
                vis[j] = true;
        }
        for(int i = 1; i <= n; i++) Set.insert(i);
        for(int i = 1; i <= n; i++) {
            for(int j = i + i; j <= n; j += i) {
                now++;
                rel[j]++;
                rel[i]++;
                fac[j].push_back(i);
            }
        }
        if(now < k) {
            puts("No");
            return 0;
        }
        if(now == k) {
            puts("Yes");
            printf("%d\n", SZ(Set));
            for(auto& t : Set) printf("%d ", t);
            puts("");
            return 0;
        }
        for(int i = n / 2 + 1; i <= n; i++) {
            if(!vis[i]) {
                vc.push_back(i), now--, Set.erase(i);
                rel[1]--;
                if(now == k) {
                    puts("Yes");
                    printf("%d\n", SZ(Set));
                    for(auto& t : Set) printf("%d ", t);
                    puts("");
                    return 0;
                }
            }
        }
        while(now > k) {
            int v = *Set.rbegin();
            if(rel[v] <= now - k) {
                now -= rel[v];
                Set.erase(v);
                for(auto& t : fac[v]) rel[t]--;
            } else {
                int who = v;
                for(auto& t : Set)
                    if(now - rel[t] <= k && rel[t] < rel[who]) who = t;
                now -= rel[who];
                Set.erase(who);
                for(auto& t : fac[who]) rel[t]--;
                while(now < k && SZ(vc)) {
                    now++;
                    Set.insert(vc.back());
                    vc.pop_back();
                }
            }
        }
        if(now == k) {
            puts("Yes");
            printf("%d\n", SZ(Set));
            for(auto& t : Set) printf("%d ", t);
            puts("");
            return 0;
        } else {
            puts("No");
        }
    }
    return 0;
}

/*
*/

猜你喜欢

转载自www.cnblogs.com/CJLHY/p/10663873.html