51nod 1406 与查询

垃圾选手练dp

考虑对于一个数,能够把它表示出来也一定可以把它某些1的位变成0变成的数表示出来

那么用大的数更新小的,容易想到每次都把这个大的数的1个1的位变成0

但是这样还是会有重复的情况

比如10010被10110和11010更新,但是这两个数都会被11110更新到

那么DP再加一维,f[i][zt]表示zt这个数当前只受到前i位是1的数的更新,对于前i-1位的更新可以直接加上,第i位的更新在当前的for循环里面处理

这样就不会重复了,同时可以发现这个是一个类似背包的东西,所以i的那维也可以省掉了

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
void write(int d)
{
    if(d<0){putchar(‘-‘);d=-d;}
    if(d>=10)write(d/10);
    putchar(d%10+‘0‘);
}

int f[1100000];
int main()
{
    int n,x,mx=0;
    n=read();
    memset(f,0,sizeof(f));
    for(int i=1;i<=n;i++)
    {
        x=read(),f[x]++;
        mx=max(mx,x);
    }

    for(int i=22;i>=0;i--)
        for(int zt=1;zt<=mx;zt++)
            if(zt&(1<<i))f[zt^(1<<i)]+=f[zt];

    f[0]=n;
    for(int i=0;i<=30;i++)
    {
        write(f[i]);
        puts("");
    }
    return 0;
}

原文地址:https://www.cnblogs.com/AKCqhzdy/p/9768476.html

时间: 2024-07-30 07:56:43

51nod 1406 与查询的相关文章

51nod 1406 与查询 dp 考虑每一位 避免重复

题目链接: http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1406 题意: 有n个整数.输出他之中和x相与之后结果为x的有多少个.x从0到1,000,000 思路: http://blog.csdn.net/bahuia/article/details/55653495 这题dp的思路很巧妙,分析一下题目,很容易想到,若已经求出一个数x的合法结果数,那么对于x位数上的子集来说,x的结果对他们也同样适用,例如,能和x=1

51nod 1406:与查询

51nod 1406:与查询 题目链接:http://www.51nod.com/onlineJudge/submitDetail.html#!judgeId=222358 题目大意:给出$n$个数,问这$n$个数与$x$做位与($\&$)后值为$x$的有多少个. DP 显然暴力是不行的. 由题目可得,若$a \& x=x$,则$x$的二进制表示中为$1$的位,$a$也必为$1$. 故若$x$和$y$仅有一位不同,且$x\&y=x$,则 与$x$做位与后值为$x$的数中 必包含 与

51nod 1406 位运算/dp

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1406 1406 与查询 题目来源: CodeForces 基准时间限制:2 秒 空间限制:131072 KB 分值: 80 难度:5级算法题 收藏 关注 有n个整数.输出他之中和x相与之后结果为x的有多少个.x从0到1,000,000 Input 第一行输入一个整数n.(1<=n<=1,000,000). 第二行有n个整数a[0],a[1],a[2],...a[n-1

51nod 最近刷题 简要题解

51nod 1564 由于数据是随机的,可以证明,对于每一个数,向左或右找比它小的数,长度是logn级别的 考虑枚举最大值 注意,对于每一个最大值,如果直接用2个循环枚举左右端点的话,理论是lognlogn级别的,但是还是很容易被卡的,换成贪心,用2个指针指着左右端点,每一次移动我们往数大的那个方向移动 代码: //File Name: nod1564.cpp //Author: long //Mail: [email protected] //Created Time: 2016年10月10日

51Nod 1571 最近等对(线段树、离线查询)

http://www.51nod.com/Challenge/Problem.html#!#problemId=1571 题解 题目要求的最近点对不太符合区间加合性,所以不能直接用线段树在线做. 我们可以先把数据离散化,求出当前点左边离他最近的点的位置,从左到右扫一遍,更新当前点的距离,然后回答以当前点为右端点的查询,题目数据量很大必须快读快写,换行不能用priintf("\n"),只能用putchar('\n');不然会慢一倍然后T掉好几个数据... 1 #define dbg(x)

51nod 1463 找朋友(线段树+离线处理)

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1463 题意: 思路: 好题! 先对所有查询进行离线处理,按照右区间排序,因为k一共最多只有10个,所有在该区间内的B数组,每次枚举K值,通过这样的方式来得到另外一个B值.但是这样得到的B值它在B数组中的位置必须在当前数的左边.如下图:(j为当前数在B数组中的位置,pos为计算得到的另一个B值在数组中的位置) 这两个数的和记录在pos中,这里pos的位置必须在j的左边,假

51nod 1174 1174 区间中最大的数

题目链接:51nod 1174 1174 区间中最大的数 ST(Sparse Table)算法学习参考博客:http://blog.csdn.net/niushuai666/article/details/6624672 O(nlogn)预处理,O(1)查询 1 #include<cstdio> 2 #include<algorithm> 3 #include<cmath> 4 using namespace std; 5 const int N = 10001; 6

戴尔维修站查询

戴尔中国大陆维修站点查询 戴尔论坛 www.dell.js.cn 1. 维修站支持机型包括: 台式机.笔记本.平板 部分维修站支持台式机.笔记本.平板.Wyse(CCC-四位数 的维修站) 2. 服务时间:周一至周日 9:00 – 18:00(周日仅提供收机服务),节假日休息 3.为节省消费者们在维修站点的排队等候时间,自2015年2月2日起,客户可通过送修预约服务网站(http://www.cisbooking.com) 或拨打800-858-0655进行送修预约,预约时段为周一到周六,9:0

【51nod 1785】数据流中的算法

Description 51nod近日上线了用户满意度检测工具,使用高级人工智能算法,通过用户访问时间.鼠标轨迹等特征计算用户对于网站的满意程度. 现有的统计工具只能统计某一个窗口中,用户的满意程度的均值.夹克老爷想让你为统计工具添加一个新feature,即在统计均值的同时,计算窗口中满意程度的标准差和中位数(均值需要向下取整). Input 第一行是整数n与k,代表有n次操作,时间窗口大小为k.  (1 <= n <= 10^6, 1 <= k <= 100) 接下来的n行,每行