CFgym 100851B-Binary vs Decimal

来源:互联网 发布:优化站和竞价站的区别 编辑:程序博客网 时间:2024/06/05 06:31

CFgym 100851B-Binary vs Decimal

 

题意:如果一个十进制数的位是它的二进制位的后缀的话,那么称这个数为bindecimal数,求第n个最小的bindecimal数。

分析:做这题的时候没想到什么解法,以为是个找规律题,然后发现题目给的note里面的bindecimal数都有一个特点,bindecimal数的后缀也是bindecimal数,但是觉得并不靠谱就放弃了,结果后面看题解给出的思路就是从这个特点出发进行bfs枚举求解的…

所以我们只需要从0、1开始每次往后面加0或者1进行搜索,注意到题目是要求出第n个最小的bindecimal数,所以按十进制数从小到大枚举,即每次先把所有的合法数先在后面加上0,如果是个bindecimal数的话,那么放进队列,之后加上1,进行同样的操作,只需要在加往后加1的数当中选取第n个就行了,每次都只需要拿bindecimal数进行枚举,时间可以承受。

判断是不是bindecimal数的话,模拟大数转换为二进制数的过程就行了,边取边判断,不相等就返回。

#include <cstdio>#include <algorithm>#include <cstring>#include <vector>#include <queue>#define LL long long#define INF 0x3f3f3f3fusing namespace std;typedef vector<int> vec;queue<vec> q;vector<vec> p;int n;int check(vec x){    int len = x.size()-1;    vec tmp = x;    int k = len;    for (int i = 0; i <= len; i++){        if ((x[0] & 1) != tmp[i]) return 0;        int t = 0;        for (int j = k; j >= 0; j--){            int c = (t*10+x[j]) & 1;            x[j] = (t*10+x[j])/2;            t = c;        }        while (!x[k]) k--;    }    return 1;}void bfs(){    vec tmp;    tmp.push_back(0);    q.push(tmp);    int cnt = 1;    tmp[0] = 1;    q.push(tmp);    while (1){        p.clear();        while (!q.empty()) p.push_back(q.front()), q.pop();        for (int i = 0; i < p.size(); i++){            tmp = p[i];            tmp.push_back(0);            if (check(tmp)) q.push(tmp);        }        for (int i = 0; i < p.size(); i++){            tmp = p[i];            tmp.push_back(1);            if (check(tmp)){                if (++cnt == n){                    for (int j = tmp.size()-1; j >= 0; j--) printf("%d", tmp[j]);                    puts("");                    return ;                }                q.push(tmp);            }        }    }}int main(){    freopen("binary.in", "r", stdin);    freopen("binary.out", "w", stdout);    scanf("%d", &n);    if (n == 1) puts("1");    else bfs();    return 0;}

看到这题就想到了poj上的一个类似的题。

Poj1426:

同样属于枚举01位判断的题,在此对比下。

题意:给定n,求出它的一个由01组成的十进制倍数。

分析:bfs搜索,并记录路径。

#include <cstdio>#include <algorithm>#include <cstring>#include <vector>using namespace std;int flag, mod, cnt, i, j;int prior[1000000], prbit[1000000];char s[110];int next[2] = {1, 0};struct mul{    int num, prev;};struct Queue{    mul q[10000000];    int front, rear;};Queue Q;void BFS(){    int a, b, c, d;    flag = cnt = 1;    mul sta = {1, 1};    Q.front = Q.rear = 0;    Q.q[Q.rear] = sta;    while (flag)    {        a = Q.q[Q.front].num;        b = Q.q[Q.front++].prev;        for (j = 0; j<2 && flag; j++)        {            prior[++cnt] = b;            prbit[cnt] = next[j];            c = (a*10+next[j])%mod;            if (c == 0)            {                i = 0;                d = cnt;                while (d != 1)                {                    s[i++] = prbit[d]+'0';                    d = prior[d];                }                s[i++] = '1';                flag = 0;                break;            }            mul temp = {c, cnt};            Q.q[++Q.rear] = temp;        }    }}int main(){    while (scanf("%d", &mod), mod)    {        memset(s, 0, sizeof(s));        BFS();        reverse(s, s+i);        puts(s);    }    return 0;}


两题都是根据题目的特点出发进行搜索求解的,当然第一题更难,第二题很容易,可以看出,只要抓住了关键,从这出发,选取看似可行的方法入手,之后如果不行的话在换方法或者优化即可,而且搜索算是一个最基本也最重要的算法吧。突然就觉得很多题目都是要挖掘其特征,灵活运用对应的算法解决的,算法本身没有优劣性,只要会运用就算暴力也会高效。

0 0
原创粉丝点击