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;
}

/*
*/

原文地址:https://www.cnblogs.com/CJLHY/p/10663873.html

时间: 2024-08-30 07:42:19

Codeforces 922F Divisibility 构造的相关文章

CodeForces 26C Parquet 构造题

题目链接:点击打开链接 #include <stdio.h> #include <string.h> #include <iostream> #include <algorithm> #include <math.h> #include <set> using namespace std; #define N 105 int n,m,a,b,c; char s[N][N]; set<char>myset; bool inm

codeforces #306D Polygon 构造

题目大意:给定n,要求构造一个凸n边形,使得每个内角都相同,每条边长度都不同 膜拜题解 其实我一开始想的是构造一个正n边形然后把每条边微移一下--不过似乎不是很好写的样子= = #include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 110 #define PI 3.14159265358979

Codeforces 1030D 【构造】

LINK 题目大意:给你n,m,k,让你在一个n*m的点阵里构造出一个面积为\(\frac{n*m}{k}\)的三角形 思路 首先要有一个结论是整点三角形的面积分母最多为2,然后就可以判断不存在的情况了 接下来就直接进行构造就可以了 #include<bits/stdc++.h> using namespace std; #define LL long long #define IL inline #define fu(a,b,c) for(LL a=b;a<=c;++a) #defin

New Roads CodeForces - 746G (树,构造)

大意:构造n结点树, 高度$i$的结点有$a_i$个, 且叶子有k个. 先确定主链, 然后贪心放其余节点. #include <iostream> #include <algorithm> #include <cstdio> #include <math.h> #include <set> #include <map> #include <queue> #include <string> #include &l

CodeForces 520C 水构造

//520C - DNA Alignment 1 #include "iostream" 2 #include "cstdio" 3 using namespace std; 4 const __int64 mod = 1e9 + 7; 5 int n; 6 char str[100010]; 7 int Count[5]; 8 9 __int64 bin(__int64 n, __int64 k) 10 { 11 __int64 res = 1; 12 while

CodeForces 597A Divisibility

水题. #include<iostream> #include<cstring> #include<cmath> #include<queue> #include<algorithm> #include<cstdio> using namespace std; long long k,L,R; int main() { scanf("%lld%lld%lld",&k,&L,&R); long

codeforces 589a(构造的字符串后,最后要加终止符,,,)

模拟注意细节,没什么好说的#include <cstdio> #include <cstring> #include <vector> #include <algorithm> #include <iostream> #include <map> #include <queue> #include <stack> #include <cmath> //#pragma comment(linker,

Codeforces 534D Handshakes 构造 模拟 贪心

题意:人们依次进大厅,后进来的人会和里面所有的人都握手, 大厅里面有三个人就 其中丧二恩就可以结伴走出大厅.给你每个人进大厅时候握手的次数.让你求一个进场顺序. 解题思路:比赛的时候是用的从后往前推.比较难,发现从前往后直接模拟就行了 . 解题代码: 1 // File Name: d.cpp 2 // Author: darkdream 3 // Created Time: 2015年04月13日 星期一 01时30分17秒 4 5 #include<vector> 6 #include&l

CodeForces 550C Divisibility by Eight(枚举)

[题目链接]click here~~ [题目大意] 给一个不超过100位的数字,要求能否删掉几位数,剩下的数能被8整除 [解题思路]:这里有个性质:如果一个数后三位能被8整除,那么这个数就能被8整除 证明:举一个5位数的例子吧, 例如 _____  _____  __              __  __                __  ___ abcde=ab000+cde=1000×ab+cde=8×125×ab+cde 很明显,8×125×ab一定是8或者125的倍数,因此当cde