zoukankan      html  css  js  c++  java
  • CF1070A Find a Number

    CF1070A Find a Number

    洛谷传送门

    题意翻译

    给定两个数d(1le d le 500)d(1≤d≤500)和s(1le sle 5000)s(1≤s≤5000),找出最小数nn使得dmid ndn且nn的各个位数之和为ss


    题解:

    暴力的思路肯定就是枚举(d)的所有倍数。

    看到第二个样例之后绝望。然后又发现了-1的情况,所以觉得正解应该是搜索。

    然后还要找最小值,所以感觉应该是BFS,然后觉得裸的BFS转不了,所以应该加个记忆化。

    嗯,于是正解的思路就拿出来了。BFS+记忆化。

    我们设(pre[d][s])为当前枚举到的各位和为(s),当前数字对(d)取模结果为(d)上一个(d,s)和位数。这样就可以用递归输出答案。

    为什么在状态设置上要加上对(d)取模呢?因为当前数字可能很大,但是其对(d)取模的结果是当前状态下唯一的,所以可以保证正确性。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    int d,s,pre[505][5005][3];
    bool v[505][5005];
    queue<int>qx,qy;
    void bfs()
    {
        v[0][0]=1;
        qx.push(0);
        qy.push(0);
        while(!qx.empty())
    	{
            int x=qx.front();
    		qx.pop();
            int y=qy.front();
    		qy.pop();
            for(int i=0;i<=9;i++)
    		{
                int xx=(10*x+i)%d,yy=y+i;
                if(v[xx][yy]||yy>s)
                    continue;
                v[xx][yy]=1;
                pre[xx][yy][0]=x;
                pre[xx][yy][1]=y;
                pre[xx][yy][2]=i;
                qx.push(xx);
                qy.push(yy);
            }
        }
    }
    void print(int x,int y)
    {
        if(!x&&!y)
            return;
        print(pre[x][y][0],pre[x][y][1]);
        printf("%d",pre[x][y][2]);
    }
    int main()
    {
    	scanf("%d%d",&d,&s);
        bfs();
        if(v[0][s]==0)
            puts("-1");
        else 
            print(0,s);
        return 0;
    }
    
  • 相关阅读:
    Yaffs文件系统简介
    网新恒天2013年校园招聘笔试
    【Android】项目中每个文件夹的作用
    唐-诗:《春江花月夜》
    汉语-词语:诗词歌赋
    汉语-词语:四季
    图书-心理学:《思考致富》
    影视-电影:《释迦摩尼佛传》
    软件开发-开发模式:极限编程
    【计算机视觉】SIFT中LoG和DoG比較
  • 原文地址:https://www.cnblogs.com/fusiwei/p/14044219.html
Copyright © 2011-2022 走看看