题解:AT_abc443_f [ABC443F] Non-Increasing Number / [SNOW] - 19
fish_love_cat · · 题解
刚过(
考虑大力搜索。具体的,我们不断的从已有状态进行转移,选择一个合法的数字接在原数字末尾。
注意到对于模
于是 vis 数组的定义就出来了。
使用 bfs 保证第一个抵达的是最小的结果,时间复杂度也容易发现是
做完了……吗?
你准备如何实现呢。
队列里面存放输出的结果和余数吗?恭喜你,字符串拼接的大常数炸飞你。
正确做法是存末尾数字和余数,然后另外开个链表,最后沿着链表把答案拎出来。
MLE 了?请不要使用 #define int long long。
做完了。
#include<bits/stdc++.h>
#define lowbit(x) x&(-x)
#define mod 998244353
using namespace std;
int vis[3000005][15];
int pre[3000005][15];
int out[3000005][15];
void solve(){
int n;
cin>>n;
queue<pair<int,int>>q;
if(n%10==0){
cout<<-1;
return;
}
if(n<10){
cout<<n;
return;
}
for(int i=1;i<10;i++){
q.push({i,i});
vis[i][i]=1;
pre[i][i]=-1;
out[i][i]=-1;
}
while(!q.empty()){
int s=q.front().first;
int x=q.front().second;
q.pop();
if(x==0){
string ret;
char c=s+'0';ret+=c;
for(int i=pre[x][s],j=out[x][s];i!=-1;){
c=j+'0';
ret+=c;
int xi=i;
int xj=j;
i=pre[xi][xj];
j=out[xi][xj];
}
reverse(ret.begin(),ret.end());
cout<<ret;
return;
}
for(int i=s;i<10;i++){
int nx=x;
nx=nx*10+i;
nx%=n;
if(!vis[nx][i]){
out[nx][i]=s;
pre[nx][i]=x;
q.push({i,nx}),vis[nx][i]=1;
}
}
}
puts("-1");
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
int t=1;
// cin>>t;
while(t--)solve();
return 0;
}
// 她的目的地是大街旁的路边摊。
// 那里好像是间诚实商店,只有放著投钱的钱箱。
// 她在那里做了坏事。
// 所以我也立刻出面制止。
//「不可以喔,要好好付钱才对。」
// 边说,我边把手放上她的肩膀。
交了 9 发。