P1602 Sramoc问题(广搜处理暴力与同余)

题目描述

话说员工们整理好了筷子之后,就准备将快餐送出了,但是一看订单,都傻眼了:订单上没有留电话号码,只写了一个sramoc(k,m)函数,这什么东西?什么意思?于是餐厅找来了资深顾问团的成员,YQ,SC,HQ,经过大量的查阅,大家获得了一些信息,Sramoc ( K , M ) 表示用数字0、1、2…、K-1组成的自然数中能被M整除的最小数。例如 K=2,M=7的时候,Sramoc( 2 , 7 ) = 1001。自然电话号码就是1001,为了尽快将快餐送出,电脑组的童鞋们埋头算起了这个齐葩的号码。。。

输入输出格式

输入格式:

 

第1行为两个整数 k, m (2≤k≤10,0≤m≤1000)。

 

输出格式:

 

仅1行,那个电话号码(最小的数)。

 

输入输出样例

输入样例#1: 复制

2 7

输出样例#1: 复制

1001

 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
#define MAXN 1005
int K,M;
bool vis[MAXN];
void bfs()
{
    int i;
    queue<long long> q;
    queue<vector<int> > q2;
    vector<int> s;
    for(i=1;i<=K-1;i++)   //i表示的是余数,所以不能为0,为0就直接结束了(下面)
    {
        q.push(i%M);        //这里取余是已经判断出传递对象了
        vis[i%M]=true;
        s.push_back(i);
        q2.push(s);        // 队列在这个循环中都是没出队列的
        s.pop_back();      //但不定数组每次都要重置 ,不定数组存的是一个数字串
    }                      //利用广搜处理暴力枚举k^a种情况a确定大小
    long long u,k;
    while(!q.empty())      //出队列才是广搜的开始
    {
        u=q.front();
        q.pop();
        s=q2.front();
        q2.pop();
        for(i=0;i<=K-1;i++)            //枚举K,和暴力一致(K>=2&&K<=10,m>=0&&m<=1000) //以暴力为基础思想的还是用 long long比较保险
        {                              //利用同余简化暴力枚举的次数,但枚举形式不变
            k=u*(10%M)+i%M;            //(x*k+y)mod m=((x mod m)*(k mod m)+(y mod m) ) mod m .//本题的k为10
                                       //  ((x*k+y)*k+i) mod m==(((x*k+y) mod m)*(k mod m)+i mod m) mod m==上述,所以可以迭代
            s.push_back(i);            //  所以每次 u取(x*k+y) mod m,也就是k%M
            if(k%M==0)                 //用同余就考虑两种对比情况,找到传递的对象
            {
                for(unsigned int j=0;j<s.size();j++) printf("%d",s[j]);
                cout<<endl;
                return;
            }
            else if(vis[k%M]==0)      //判断传递对象是否有
            {
                vis[k%M]=true;
                q.push(k%M);
                q2.push(s);
            }
            s.pop_back();    //每次压入不定数组都有删除最后一个元素的操作,把这个i去掉,同层枚举吧
        }
    }
}
//不用同余的暴力枚举
/*
while(!q.empty())
    {
        u=q.front();
        q.pop();
        s=q2.front();
        q2.pop();
        for(i=0;i<=K-1;i++)
        {
            k=u*10+i;     //不同点1
            s.push_back(i);
            if(k%M==0)    //不同点2
            {
                for(unsigned int j=0;j<s.size();j++) printf("%d",s[j]);
                cout<<endl;
                return;
            }
                q.push(k);   //不同点3
                q2.push(s);
                s.pop_back();
        }
    }
    所以利用同余就是抓住了 (x*k+y)mod m=((x mod m)*(k mod m)+(y mod m) ) mod m,进行迭代
*/
int main()
{
    cin>>K>>M;
    bfs();
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值