51 NOD 1315 合法整数集(思维 + 模拟)

传送门

一个整数集合S是合法的,指S的任意子集subS有Fun(SubS)!=X,其中X是一个固定整数,Fun(A)的定义如下:

A为一个整数集合,设A中有n个元素,分别为a0,a1,a2,…,an-1,那么定义:Fun(A)=a0 or a1 or … or an-1;Fun({}) = 0,即空集的函数值为0.其中,or为或操作。

现在给你一个集合Y与整数X的值,问在集合Y至少删除多少个元素能使集合Y合法?

例如:Y = {1,2,4},X=7;显然现在的Y不合法,因为 1 or 2 or 4 = 7,但是删除掉任何一个元素后Y将合法。所以,答案是1.

Input

第一行两个整数N,X,其中N为Y集合元素个数,X如题所述,且1<=N<=50,1<=X<=1,000,000,000.

之后N行,每行一个整数yi,即集合Y中的第i个元素,且1<=yi<=1,000,000,000.

Output

一个整数,表示最少删除多少个元素。

Input示例

5 7

1

2

4

7

8

Output示例

2

解题思路:

这个题还是很注意细节的,我就错了很多遍,都是泪啊。好了,话不多说,说一下解题思路:

因为是保证或的,所以将 x 转化为2进制之后考虑有 1 的那一位就行了,然后注意一下,比x大的可以直接跳过,因为逻辑或之后肯定还是比x大的,不可能等于x,然后在需要跳过的就是,当前的x的这一位是0,然而集合中的数的这一位恰好为1那么也跳过,逻辑或之后肯定不是 x 了,所以只需要考虑 x 的是1的那些位就行了,然后找最小的。

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int MAXN = 105;
typedef long long LL;
LL a[MAXN], tp[MAXN];
int b[MAXN];
int main()
{
    LL n, x;
    while(cin>>n>>x)
    {
        memset(b, 0, sizeof(b));
        LL tmp = x;
        int cnt = 0, m = 0;
        while(tmp)
        {
            b[cnt++] = (tmp & 1);
            tmp >>= 1;
        }
        LL xx;
        for(int i=0; i<n; i++)
        {
            cin>>xx;
            if(xx <= x)
            {
                int cnt1 = 0;
                LL tt = xx;
                while(tt)
                {
                    int ttt = (tt&1);
                    if(ttt && (!b[cnt1]))
                        goto endW;
                    tt>>=1;
                    cnt1++;
                }
                a[m++] = xx;
            }
            endW:;
        }
        int Min = 999999;
        for(int j=0; j<cnt; j++)
        {
            if(b[j])
            {
                int ans = 0;
                for(int i=0; i<m; i++)
                {
                    if(a[i]&1)
                        ans++;
                    a[i]>>=1;
                }
                Min = min(Min, ans);
            }
            else
                for(int i=0; i<m; i++)
                    a[i]>>=1;
        }
        cout<<Min<<endl;
    }
    return 0;
}
/**
3 1
12571295
2174218
2015120
**/
时间: 2024-11-05 20:46:44

51 NOD 1315 合法整数集(思维 + 模拟)的相关文章

51nod 1315 合法整数集 (位操作理解、模拟、进制转换)

1315 合法整数集 题目来源: TopCoder 基准时间限制:1 秒 空间限制:131072 KB 分值: 10 难度:2级算法题 收藏 关注 取消关注 一个整数集合S是合法的,指S的任意子集subS有Fun(SubS)!=X,其中X是一个固定整数,Fun(A)的定义如下: A为一个整数集合,设A中有n个元素,分别为a0,a1,a2,...,an-1,那么定义:Fun(A)=a0 or a1 or ... or an-1:Fun({}) = 0,即空集的函数值为0.其中,or为或操作. 现在

【51nod-1315】合法整数集(数位)

[思路] 既然是or操作,将数转化为二进制,数位是1,对应的数组元素+1,再将x转为成二进制,只要查找X为1的位置,将之前存放的数组数字找个最小的输出就可以了. 但是并不是所有的数都要参与or,因为有些数的位数>X,显然这些数是不用删除的,所以不用让这些数加到数组里.还有哪些数呢?当有些数的位数是1,而X对应的位数是0,这些数也是一定不用删除的.综合以上只要满足(x|xx)> x就可以参与or. [code] #include <bits/stdc++.h> using names

51 nod 1427 文明 (并查集 + 树的直径)

1427 文明 题目来源: CodeForces 基准时间限制:1.5 秒 空间限制:131072 KB 分值: 160 难度:6级算法题 安德鲁在玩一个叫“文明”的游戏.大妈正在帮助他. 这个游戏里面有n个城市和m条双向的道路.城市从1到n编号.对于每一对城市,他们之间要么有唯一的一条道路,要么就是不可互达.一条道路的定义是一个包含不同城市的序列 v1, v2,...,vk ,  vi  和  vi+1 (1≤ i < k)之间有直接的一条道路相连.这条道路的长度是k-1.两个城市在同一区域的

51 nod 1515 明辨是非(并查集合并)

1515 明辨是非题目来源: 原创基准时间限制:1 秒 空间限制:131072 KB 分值: 160 难度:6级算法题 给n组操作,每组操作形式为x y p. 当p为1时,如果第x变量和第y个变量可以相等,则输出YES,并限制他们相等:否则输出NO,并忽略此次操作. 当p为0时,如果第x变量和第y个变量可以不相等,则输出YES,并限制他们不相等 :否则输出NO,并忽略此次操作. Input 输入一个数n表示操作的次数(n<=1*10^5) 接下来n行每行三个数x,y,p(x,y<=1*10^8

51 nod 1439 互质对(Moblus容斥)

1439 互质对 题目来源: CodeForces 基准时间限制:2 秒 空间限制:131072 KB 分值: 160 难度:6级算法题 有n个数字,a[1],a[2],…,a[n].有一个集合,刚开始集合为空.然后有一种操作每次向集合中加入一个数字或者删除一个数字.每次操作给出一个下标x(1 ≤ x ≤ n),如果a[x]已经在集合中,那么就删除a[x],否则就加入a[x]. 问每次操作之后集合中互质的数字有多少对. 注意,集合中可以有重复的数字,两个数字不同当且仅当他们的下标不同. 比如a[

51 nod 1610 路径计数(Moblus+dp)

1610 路径计数 基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题 路径上所有边权的最大公约数定义为一条路径的值. 给定一个有向无环图.T次修改操作,每次修改一条边的边权,每次修改后输出有向无环图上路径的值为1的路径数量(对1,000,000,007取模). Input 第一行两个整数n和m,分别表示有向无环图上的点数和边数.(1<=n<=100,1<=m<=50,000) 第2~m+1行每行三个数x,y,z,表示有一条从x到y权值为z的边.(1

51 nod 1405 树的距离之和

1405 树的距离之和 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 给定一棵无根树,假设它有n个节点,节点编号从1到n, 求任意两点之间的距离(最短路径)之和. Input 第一行包含一个正整数n (n <= 100000),表示节点个数. 后面(n - 1)行,每行两个整数表示树的边. Output 每行一个整数,第i(i = 1,2,...n)行表示所有节点到第i个点的距离之和. Input示例 4 1 2 3 2 4 2 Output示例 5 3 5

51 nod 1421 最大MOD值

1421 最大MOD值 题目来源: CodeForces 基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题 有一个a数组,里面有n个整数.现在要从中找到两个数字(可以是同一个) ai,aj ,使得 ai mod aj 最大并且 ai ≥ aj. Input 单组测试数据. 第一行包含一个整数n,表示数组a的大小.(1 ≤ n ≤ 2*10^5) 第二行有n个用空格分开的整数ai (1 ≤ ai ≤ 10^6). Output 输出一个整数代表最大的mod值. I

51 nod 1394 1394 差和问题(线段树)

1394 差和问题基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题 有一个多重集合S(即里面元素可以有重复),初始状态下有n个元素,对他进行如下操作: 1.向S里面添加一个值为v的元素.输入格式为1 v 2.向S里面删除一个值为v的元素.输入格式为2 v 3.询问S里面的元素两两之差绝对值之和.输入格式为3 对于样例, 操作3,|1-2|+|1-3|+|2-3|=4 操作1 4之后,集合中的数字为1 2 3 4 操作3,|1-2|+|1-3|+|2-3|+|1-