codeforces round#748 div3 F. Red-Black Number

n,a,b <= 40 考虑4维dp
dp[i][j][k][l]状态表示,数字取到第i位,红色取了l个且组成的数字%a == j,黑色去了(n-l)个且组成数字%b == k,这样一个方案是否可行
转移就是对当前数字分别取红色和黑色:
取红色的话:dp[i + 1][(j * 10 + x[i])%a][k][l + 1]方案将变得可行
取黑色的话:dp[i + 1][j][(k * 10 + x[i])][l]方案将变得可行
最后看dp[n][0][0][?]方案是否可行,选择差距最小的进行输出即可,在dp的过程中记得存储转移的来源即可,dfs回溯一下
代码如下:

#include<bits/stdc++.h>
#pragma comment(linker, "/stack:200000000")
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#define debug(x) cout<<#x<<" is "<<x<<endl
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define DBG 0
const int N = 40 + 5;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const ll LLINF = (1LL<<60);
using namespace std;
const int mod = 998244353;
ll fast_pow(ll a,ll b){ll ans = 1;while(b){if(b&1)ans = (ans * a)%mod;a = (a * a)%mod;b>>=1;}return (ans%mod);}
inline ll read(){ll X=0; bool flag=1; char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') flag=0; ch=getchar();}while(ch>='0'&&ch<='9') {X=(X<<1)+(X<<3)+ch-'0'; ch=getchar();}if(flag) return X;return ~(X-1);}
inline void write(ll X){if(X<0) {X=~(X-1); putchar('-');}if(X>9) write(X/10);putchar(X%10+'0');}
typedef pair<int,int> pii;
typedef vector<int> vi;
inline void fastIO(){ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);}
inline void time_cost(clock_t start_time,clock_t end_time){cout << "The run time is: " <<(double)(end_time - start_time) / CLOCKS_PER_SEC << "s" << endl;}
inline void init(){	
	
}
struct node{
	
	int color,last;
	node(){
		color = last = -1;
	} 
	node(int _c,int _l):color(_c),last(_l){
	}
	
};
node dp[N][N][N][N];
int x[N],n,a,b;


void show(int i,int j,int k,int l){
	if(i == 0)return;
	int color = dp[i][j][k][l].color;
	int last = dp[i][j][k][l].last;
	if(color == 1)
		show(i - 1,last,k,l - 1);
	else
		show(i - 1,j,last,l);
	printf("%c",color == 1?'R':'B');
}
inline void solve(){
	init();
	scanf("%d%d%d",&n,&a,&b);
	for(int i = 0;i < n;i++)scanf("%1d",&x[i]);//一个一个的读
	for(int i = 0;i < N;i++)
		for(int j = 0;j < N;j++)
			for(int k = 0;k < N;k++)
				for(int l = 0;l < N;l++)
					dp[i][j][k][l].color = dp[i][j][k][l].last = -1;
	dp[0][0][0][0].color = 1;
	for(int i = 0;i < n;i++)
		for(int j = 0;j < a;j++)
			for(int k = 0;k < b;k++)
				for(int l = 0;l <= i;l++)if(dp[i][j][k][l].color != -1){
					int & c1 = dp[i + 1][(j * 10 + x[i]) % a][k][l + 1].color;
					int & l1 = dp[i + 1][(j * 10 + x[i]) % a][k][l + 1].last;
					int & c2 = dp[i + 1][j][(k * 10 + x[i]) % b][l].color;
					int & l2 = dp[i + 1][j][(k * 10 + x[i]) % b][l].last;
					if(c1 == -1){
						c1 = 1;//如果选红色
						l1 = j;
					}
					if(c2 == -1){
						c2 = 2;//如果选黑色
						l2 = k;
					}
				}
	for(int i = 0;i <= n/2;i++){
		if(n / 2 + i < n  && dp[n][0][0][n / 2 + i].color != -1){
			show(n,0,0,n / 2 + i);
			puts("");
			return;
		}
		if(n /2 - i > 0 && dp[n][0][0][n / 2 - i].color != -1){
			show(n,0,0,n/2 - i);
			puts("");
			return;
		}
	}
	printf("-1\n");
} 
int main(){
//	fastIO();
#if DBG
	freopen("input.txt","r",stdin);
	freopen("output.txt","w",stdout);
#endif
	int t;
	scanf("%d",&t);
	while(t--)
		solve();

	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值