Codeforces Round #748 (Div. 3) F. Red-Black Number (dp)

传送门

给定一串长度为n的数字,可以把每一位涂上红色或黑色,要求每种颜色至少有一位,每位都必须涂色,最终红色位构成的数可以整除A,黑色位构成的数可以整除B.
输出红 黑数相差最小的一种涂法,如果不存在,输出-1.

在这里插入图片描述

本来有2^40个状态,我们需要合并某些状态以减少状态数目。

这种涉及整除,且除数比较小的情况,我们可以拿模数当成一维状态。

dp[pos][mod_a][mod_b][na]表示当前枚举到第pos位,红色数对A的模数为mod_a,黑色对B的模数为mod_b,总共有na个红色,状态下的涂色答案。
当增加一个red, mod_ a = (mod_a*10+num[pos])%a
直接dfs。

#include<bits/stdc++.h>
using namespace std;
//#pragma GCC optimize(2)
#define ull unsigned long long
#define ll long long
#define pii pair<int, int>
const int maxn = 4e5 + 10;
const ll mod = 998244353;
const ll inf = (ll)4e17+5;
const int INF = 1e9 + 7;
const double pi = acos(-1.0);
ll inv(ll b){
    
    if(b==1)return 1;return(mod-mod/b)*inv(mod%b)%mod;}
inline ll read()
{
    
    
    ll x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){
    
    if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){
    
    x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
//40长度的数字 每个数字涂成红或黑色 红色组成的数字可以整除a 黑色可以整除b  输出黑红相差最小的一种方案
//1<=a b <=40
//注意a b很小 且之和除法有关 所以以模a b的余数作为状态的一维
//dp[i][j][k][l] dfs 或者 bfs
char ans[50],t[50];
int d=INF;
int n,a,b;
int s[50];
bool f=0;
bool vis[45][45][45][45];
void dfs(int pos,int la,int lb,int nr)//枚举完了前pos-1
{
    
    
    if(vis[pos][la][lb][nr]) return;
    vis[pos][la][lb][nr]=1;
    if(pos==n+1)
    {
    
    
        if(!la && !lb && abs(n-2*nr)<d && nr<n && nr>0) 
        {
    
    
            d=abs(n-2*nr);
            for(int i=1;i<=n;i++) ans[i]=t[i];
        }
        return ;
    }
    t[pos]='R';
    dfs(pos+1,(la*10+s[pos])%a,lb,nr+1);
    t[pos]='B';
    dfs(pos+1,la,(lb*10+s[pos])%b,nr);
}
int main()
{
    
    
    int T;cin>>T;
    while(T--)
    {
    
    
        scanf("%d%d%d",&n,&a,&b);
        for(int i=1;i<=n;i++) scanf("%01d",s+i);
        f=0;ans[n+1]=0;d=INF;
        memset(vis,0,sizeof vis);
        dfs(1,0,0,0);
        if(d==INF) puts("-1");
        else printf("%s\n",ans+1);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_46030630/article/details/120778419
今日推荐