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

sicily 1214

时间:2015-05-27 15:56:00      阅读:121      评论:0      收藏:0      [点我收藏+]

标签:

题目链接:sicily 1214

解题思路:
首先我觉得这是一道很好而且比较难的题,难度在于找规律。
题目告诉我们,n是一个很大的数(刚好在unsigned的范围内),这样的话,直接模拟是必然超时的,所以,我们需要根据题目的三条公式来推导a[n]。
这个规律我找了很久也没能找到,最后直接拿来用的,怎么想得到的我也不懂。规律如下:如果n的二进制形式满足回文序列的形式,那么a[n]=n。
得到这个规律,那么我们的题目就可以转换成找[1,n]中找到所有的数i,i满足二进制形式是回文序列。前面已经排除掉暴力模拟这个解法了,那么我们现在就只能构造了。考虑到i的二进制顶多也就是32位,回文序列的话我们可以只看16位,所以我们可以暴力枚举前16位,然后再用翻转操作求得整个回文序列,这样时间复杂度是2^16,可以接受。
之后的事情就是深搜暴力枚举啦,不再废话!

代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

unsigned n,tmp;
unsigned cnt,ans;
const unsigned delta=1;

unsigned getLen(unsigned num)
{
    unsigned len=0;
    while(num)
        num>>=1,len++;
    return len;
}

unsigned reverse(unsigned num)
{
    unsigned res=0;
    while(num) {
        res=(res<<1)|(num&1);
        num>>=1;
    }
    return res;
}

void cal(unsigned num)
{
    if(num==0)
        return; 
    unsigned len=getLen(num),res=0;
    if(((num<<len)|reverse(num))<=n)
        ans++;
    if(((num<<len-1)|reverse(num>>1))<=n)
        ans++;
}

void dfs(unsigned sum,int cnt)
{
    if(cnt==0)
    {
        cal(sum);
        return;
    }
    dfs(sum<<1,cnt-1);
    dfs((sum<<1)+delta,cnt-1);
}

int main()
{
    while(~scanf("%u",&n))
    {
        ans=0;
        dfs(0,16);
        printf("%u\n",ans);
    }

    return 0;
}

总结:
1、用二进制的思想考虑算法
2、多使用位运算

sicily 1214

标签:

原文地址:http://blog.csdn.net/fuyukai/article/details/46046127

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