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;
    }
    
  • 相关阅读:
    Android Wifi BT的工作流程和porting(精)
    ioctl命令详解
    android 编译库过程
    git恢复repo start 后丢失的修改记录
    Android Bluetooth 分析(精)
    SDIO总线 驱动
    提取高通最新代码patch
    linux设备驱动——andriod平台wlan驱动
    推送现有git到远程服务器并创建新分支
    c++继承经典例子
  • 原文地址:https://www.cnblogs.com/fusiwei/p/14044219.html
Copyright © 2011-2022 走看看