http://codeforces.com/contest/1070
题意:给出两个正整数 d 和 s ,求最小的正整数 n ,使得 n 为 d 的倍数,且 n 的每一位加起来等于 s 。
思路
不难想到搜索,但是 n 可能很大,以至于超出 long long 的范围,显然这个题还没有复杂到综合考察大数运算。所以在这里使用一个带有数论知识的DP。vis[i][j] i为余数 j为位数和。根据位数进行BFS
1.位数和等于s ,mod等于d的时候是答案
2.如果位数和>s就不入队
3.剩下的每次入队前都mod d ,加上那位数。
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<map>
#include<set>
#include<deque>
#include<queue>
#include<stack>
#include<bitset>
#include<string>
#include<fstream>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
int vis[510][5010];
struct node{
int mod;
int sum;
string str;
node(){};
node(int mod_,int sum_,string str_)
{
mod=mod_;
sum=sum_;
str=str_;
}
}r,rr;
int s,d;
string bfs()
{
queue<node>q;
q.push(node(0,0,""));
while(q.size())
{
r=q.front();
q.pop();
if(r.mod==0&&r.sum==s)
{
return r.str;
}
if(r.sum<=s)
{
for(int i=0;i<10;i++)
{
int mod=(r.mod*10+i)%d;
int sum=r.sum+i;
if(!vis[mod][sum]) // 判断之前是否出现过
迷了好久 当时一直在想 是否存在两个不同的数 他们的余数相等 各个位数相加的和相同
这两个数应该都放进去 继续接下来的操作啊 后来发现并不是这样 这道题还和d 和 s相关
如果他们的余数 和 相等的数 我们接下来干的时候+i 这样的话这些数还是相同 所以没有必要
并且我们是0-9开始遍历的 所以一开始拿到的就是最小的数
{
vis[mod][sum]=1;
q.push(node(mod,sum,r.str+(char)(i+'0')));
}
}
}
}
return "-1";
}
int main()
{
cin>>d>>s;
cout<<bfs()<<endl;
return 0;
}
好像关于找数字的题 如果模拟不出来 就得用 搜索