牛客5248H 紙牌遊戲

首先一個都知道的性質:一個數能被3整除,那麼其數位和也能被3整除。

首先能想到的就是統計每個數 ii 出現的次數 num[i]num[i],然後從高位(9>0)(9-->0)枚舉,

那麼對於數ii,可以選的最大數量就是tpnum=min(cnt,num[i])tpnum = min(cnt,num[i])

cnt爲目前還需要多少個數字,但是可能剛好選取 tpnumtpnumii, 最後的答案不能被3整除,

所以我們枚舉選的個數爲tpnumtpnum1,tpnum2tpnum,tpnum-1,tpnum-2,因爲它們mod3mod3都是[0,1,2][0,1,2],肯定能找到答案(前提是有解)

最後直接dfs搜一遍所有情況,取一個最大的情況。還有就是前導0要判一下。

9>09-->0 dfs一遍,每個位置最多33個可能,複雜度O(310)O(3^{10})

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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章