首先一個都知道的性質:一個數能被3整除,那麼其數位和也能被3整除。
首先能想到的就是統計每個數 出現的次數 ,然後從高位枚舉,
那麼對於數,可以選的最大數量就是
cnt爲目前還需要多少個數字,但是可能剛好選取 個, 最後的答案不能被3整除,
所以我們枚舉選的個數爲,因爲它們都是,肯定能找到答案(前提是有解)
最後直接dfs搜一遍所有情況,取一個最大的情況。還有就是前導0要判一下。
從 dfs一遍,每個位置最多個可能,複雜度
code
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
const int man = 2e5+10;
typedef long long ll;
const ll mod = 1e9+7;
char s[man];
int num[10],ans[10],tp[10],k;
bool f;
bool Max(){//判斷之前的是否比目前的小
for(int i = 9;i >= 0;i--){
if(ans[i]>tp[i])return 0;
else if(ans[i]<tp[i])return 1;
}
return 0;
}
void update(){//更新答案
for(int i = 0;i <= 9;i++){
ans[i] = tp[i];
}
}
void dfs(int pos,int cnt,int m){//pos表示當前的數字,cnt表示還需要多少個數,m表示選的數的和取餘。
if(pos<0){
if(!cnt&&!m&&Max())update(),f = 1;
return;
}
int tpnum = min(cnt,num[pos]);//目前最多能取的值
if(cnt==k&&pos==0)tpnum = min(tpnum,1);//判前導0
for(int i = tpnum;i >= max(0,tpnum-2);i--){//枚舉選的個數
tp[pos] = i;
dfs(pos-1,cnt-i,(m+i*pos)%3);
}
}
int main() {
#ifndef ONLINE_JUDGE
//freopen("in.txt", "r", stdin);
//freopen("out.txt","w",stdout);
#endif
int t;
scanf("%d",&t);
while(t--){
scanf("%s%d",s+1,&k);
f = 0;
for(int i =0 ;i <= 9;i++){
num[i] = ans[i] = tp[i] = 0;
}
for(int i = 1;s[i]!='\0';i++){
num[s[i]-'0']++;
}
dfs(9,k,0);
if(f){
for(int i = 9;i >= 0;i--){
if(ans[i]){
for(int j = 1;j <= ans[i];j++){
printf("%d",i);
}
}
}printf("\n");
}else cout << "-1\n";
}
return 0;
}