标签:ras ref 数字 scanf 删掉 pop lld ret cto
我们考虑删数字
首先我们可以发现有一类数很特殊就是大于 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; } /* */
Codeforces 922F Divisibility 构造
标签:ras ref 数字 scanf 删掉 pop lld ret cto
原文地址:https://www.cnblogs.com/CJLHY/p/10663873.html