poj 1426 Find The Multiple (bfs / dfs)

6 篇文章 0 订阅
4 篇文章 0 订阅

题目链接:poj 1426

Find The Multiple

Time Limit: 1000MS Memory Limit: 10000K
Special Judge

Description

Given a positive integer n, write a program to find out a nonzero multiple m of n whose decimal representation contains only the digits 0 and 1. You may assume that n is not greater than 200 and there is a corresponding m containing no more than 100 decimal digits.

Input

The input file may contain multiple test cases. Each line contains a value of n (1 <= n <= 200). A line containing a zero terminates the input.

Output

For each value of n in the input print a line containing the corresponding value of m. The decimal representation of m must not contain more than 100 digits. If there are multiple solutions for a given value of n, any one of them is acceptable.

Sample Input

2
6
19
0

Sample Output

10
100100100100100100
111111111111111111

给你一个n,让你找出一个数m,满足两个条件:
1.它的每一个数位不是1就是0;
2.它必须是n的倍数;

思路:搜索,先从最高位开始(最高位必为1),在末尾逐次加1或者0,每加一次都判断一次是否为n的倍数。然而写一半发现好像还要处理一下大数问题。略尴尬。于是默默滚去搜题解。

同余模定理:
将大数问题转化为模,每一步都计算新的模的值。
(a * b) % n = (a % n * b % n) % n
(a + b) % n = (a % n + b % n) % n

借用discuss里一位仁兄的话,本题树大解浅。说是树大,似乎dfs会比较有利,但是虽说最优解浅,却有多解,dfs得到的第一个解很可能是深解,本题只看题目的话估计出的解空间为2^100(当然实际上并没有这么大),找深解会浪费比较多的时间,这样分析的话bfs应该要更合适一些。

之前没写过dfs剪枝,暴力全搜必然各种炸,后来根据同余模定理和bfs的写法想到dfs就和它一样,遇到与之前同模的情况就剪掉,避免循环(就像走迷宫原地绕圈圈一样,徒增无用的计算)。

然后dfs 750ms卡过……直接在bfs的代码上改成了dfs,但由于dfs的特性,我这份dfs代码找解的时间整体要比bfs长。

最后就是discuss里面比较有意思的,大家都做过完了后发现bfs搜出来的最优解最大也就19位数,于是就有人直接用unsign long long写了暴力的dfs,解空间大于2^19就直接停止往下搜,时间缩短了很多,但总体来说这不是个常规解题思路,不知道这个数据范围卡的是不是出题者故意为之……然后还看见有人用自动机写???

discuss的代码:poj 1426 discuss 又短又暴力的dfs代码

bfs:

#include <iostream>
#include <string>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <ctime>
#include <cmath>
#include <queue>
#include <map>
#define M 205
#define INF 0x3f3f3f3f

using namespace std;

struct node
{
    string num;
    int mod;
}st, tmp, t;

int n;
bool vis[M];

void bfs()
{
    memset(vis, true, sizeof(vis));
    st.mod = 1 % n;
    queue<node> Q;
    Q.push(st);
    while(!Q.empty())
    {
        tmp = Q.front();
        Q.pop();
        int mod1 = (tmp.mod * (10 % n) + 1 % n) % n;//在末位加1
        int mod2 = (tmp.mod * (10 % n)) % n;//在末位加0
        if(mod1)
        {
            if(vis[mod1])
            {
                t = tmp;
                t.num += "1";
                t.mod = mod1;
                vis[mod1] = false;
                Q.push(t);
            }
        }
        else
        {
            cout << tmp.num << "1" << endl;
            break;
        }
        if(mod2)
        {
            if(vis[mod2])
            {
                t = tmp;
                t.num += "0";
                t.mod = mod2;
                vis[mod2] = false;
                Q.push(t);
            }
        }
        else
        {
            cout << tmp.num << "0" << endl;
            break;
        }
    }
}

int main()
{
    st.num = "1";
    while(scanf("%d", &n) && n)
    {
        bfs();
    }
    return 0;
}

运行结果:
这里写图片描述

dfs:

#include <iostream>
#include <string>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <ctime>
#include <cmath>
#include <queue>
#include <map>
#define M 205
#define INF 0x3f3f3f3f

using namespace std;

struct node
{
    string num;
    int mod;
}st, tmp, t;

int n;
bool vis[M], flag;

void dfs(node tmp)
{
    if(flag || tmp.num.size() > 100)    return;
    int mod1 = (tmp.mod * (10 % n) + 1 % n) % n;
    int mod2 = (tmp.mod * (10 % n)) % n;
    if(mod1)
    {
        if(vis[mod1])
        {
            t = tmp;
            t.num += "1";
            t.mod = mod1;
            vis[mod1] = false;
            dfs(t);
        }
    }
    else if(tmp.num.size() < 100 && !flag)
    {
        cout << tmp.num << "1" << endl;
        flag = true;
    }
    if(mod2)
    {
        if(vis[mod2])
        {
            t = tmp;
            t.num += "0";
            t.mod = mod2;
            vis[mod2] = false;
            dfs(t);
        }
    }
    else if(tmp.num.size() < 100 && !flag)
    {
        cout << tmp.num << "0" << endl;
        flag = true;
    }

    vis[mod1] = vis[mod2] = true;//回溯,若直接写在dfs语句后面,某些情境下会死循环。
}

int main()
{
    st.num = "1";
    while(scanf("%d", &n) && n)
    {
        memset(vis, true, sizeof(vis));
        flag = false;
        st.mod = 1 % n;
        dfs(st);
    }
    return 0;
}

运行结果:
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值