给定一串长度为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;
}