码迷,mamicode.com
首页 > 其他好文 > 详细

201502028模拟赛

时间:2015-02-28 20:16:53      阅读:137      评论:0      收藏:0      [点我收藏+]

标签:

蒟蒻表示只能在看了题解之后a掉第一题。。。

T1

题目大意:用一个数a[]的二进制表示一个集合(a[]=5=(101)2,表示集合{1,3}),求a[i]的子集中满足不是a[i-b[i]]~a[i-1]任何一个的子集的个数。

思路:搜索每一个子集,保存一下各种集合的最后一次出现的地方,如果在要求的范围之外就可以取,更新数组,否则就不能取,然后输出就可以了。因为位运算是个渣,所以就用的dfs(调小常数,有两点措施,一是把这个子集的十进制数当参数传入并变化;二是用数组保存2的几次方,比一遍遍的位运算要快。),效果也不错,没有超时。

技术分享
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int la[100001]={0},er[20]={0},a[100001]={0},b[100001]={0},ci=0,jie[20]={0};
void zer(int x)
{
    int i=0;
    memset(er,0,sizeof(er));
    while(x>0)
    {
        if (x%2==1)
        {
            ++er[0];er[er[0]]=i;
        }
        x>>=1;
        ++i;
    }
}
void work(int i,int x,int t)
{
    int j;
    if (i>er[0])
    {
        if (la[t]<x-b[x]&&t>0) 
          ++ci;
        la[t]=x;
        return;
    }
    work(i+1,x,t);
    work(i+1,x,t+jie[er[i]+1]);
}
int main()
{
    freopen("hope.in","r",stdin);
    freopen("hope.out","w",stdout);
    
    int n,i,j;
    jie[1]=1;
    for (i=2;i<=19;++i) jie[i]=jie[i-1]<<1;
    scanf("%d",&n);
    for (i=1;i<=n;++i)
    {
        scanf("%d%d",&a[i],&b[i]);
        zer(a[i]);ci=0;
        work(1,i,0);
        printf("%d\n",ci);
    }
    
    fclose(stdin);
    fclose(stdout);
}
View Code

 

201502028模拟赛

标签:

原文地址:http://www.cnblogs.com/Rivendell/p/4306122.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!