HDU 1104 Remainder (BFS)

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=1104


题意:给你一个n、m、k,有四种操作n+m,n-m,n*m,n%m,问你最少经过多少步,使得最后的结果=(初始n+1)%k

题解:很明显的BFS,然后我就很快写,果断RE,发现里面可能有负数,改了之后还是错了,看了discuss才发现原来要%mk,现在还是不是很懂为什么,这里discuss有人给出了解释——

解释一下为什么要%mk:

对于N来说,其中的过程会有N+m,N-m,以及N*m,按照正常的步骤来说,统一%K,但是因为有N%m的插足,
例如: (N+m-m*m%m)%k  (从左到右依次执行,没有优先级)
            (N%k+m%k-m%k*m%k%m%k)%k这两个是绝对不相等的
但是统一%mk是相等的,因为你%mk,是对所有的()里的数进行的,而第二个式子中因为对除最后一个数外进行的事%mk,而其他数进行的仅是%k所以不相等。


AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <list>
#include <deque>
#include <queue>
#include <iterator>
#include <stack>
#include <map>
#include <set>
#include <algorithm>
#include <cctype>
#include <ctime>
#pragma comment(linker, "/STACK:16777216")
using namespace std;

typedef __int64 LL;
const int N=1001005;
const int M=555555;
const int INF=0x3f3f3f3f;
const double PI=acos(-1.0);
const double eps=1e-7;

int n,m,k,km;
int ans;
bool vis[N];
struct xh
{
    int yu,step;
    string s;
}w,e,q[N];//数组模拟队列

void BFS()
{
    int he=0,ta=0;
    memset(vis,0,sizeof(vis));
    w.yu=(n%km+km)%km;
    w.step=0;
    w.s="";
    q[ta++]=w;
    vis[w.yu]=1;
    while(he!=ta)
    {
        e=q[he++];
        if((e.yu%k+k)%k==ans)
        {
            cout<<e.step<<endl;
            cout<<e.s<<endl;
            return ;
        }

        w=e;
        w.yu=((w.yu+m)%km+km)%km;//这个地方可能为负,要注意
        if(!vis[w.yu])
        {
            vis[w.yu]=1;
            w.s+='+';
            w.step++;
            q[ta++]=w;
        }


        w=e;
        w.yu=((w.yu-m)%km+km)%km;
        if(!vis[w.yu])
        {
            vis[w.yu]=1;
            w.s+='-';
            w.step++;
            q[ta++]=w;
        }

        w=e;
        w.yu=((w.yu*m)%km+km)%km;
        if(!vis[w.yu])
        {
            vis[w.yu]=1;
            w.s+='*';
            w.step++;
            q[ta++]=w;
        }

        w=e;
        w.yu=(w.yu%m+km)%km;
        if(!vis[w.yu])
        {
            vis[w.yu]=1;
            w.s+='%';
            w.step++;
            q[ta++]=w;
        }
    }
    puts("0");
}

int main()
{
    while(cin>>n>>k>>m)
    {
        if(n==0&&k==0&&m==0)
            break;
        km=k*m;
        ans=((n+1)%k+k)%k;
        BFS();
    }
    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值