返回顶部

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

  • 题意:有一长度为\(n\)的数组,现在需要将每个数字染成黑色或红色,然后从左往右,红色数字拼接在一起,黑色数字拼接在一起,得到的两个数能够分别被\(A\)\(B\)整除,同时黑色和红色涂色数尽可能相近,输出涂色方案。

  • 题解:数据范围比较小,考虑四维dp,设\(dp[i][j][a][b]\)表示当前红色涂了\(i\)个,黑色涂了\(j\)个,上一个涂红色的余数为\(a\),上一个涂黑色的余数为\(b\),假如现在选红色并且上一个状态存在,那么状态转移方程为:\(dp[i][j][(a*10+(s[i+j]-'0'))\mod A][b]=[1,a]\).\([1,a]\)表示当前涂红色,并且从余数\(a\)转移过来。黑色同理,最后找到\(|r-b|\)最小的位置再还原路径即可。

  • 代码

    #include <bits/stdc++.h>
    #define ll long long
    #define fi first
    #define se second
    #define pb push_back
    #define me memset
    #define rep(a,b,c) for(int a=b;a<=c;++a)
    #define per(a,b,c) for(int a=b;a>=c;--a)
    const int N = 1e6 + 10;
    const int mod = 1e9 + 7;
    const int INF = 0x3f3f3f3f;
    using namespace std;
    typedef pair<int,int> PII;
    typedef pair<ll,ll> PLL;
    ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
    ll lcm(ll a,ll b) {return a/gcd(a,b)*b;}
    
    char s[N];
    PII dp[50][50][50][50];
    char ans[N];
    
    int main() {
    	int _;
    	scanf("%d",&_);
    	while(_--){
    		int n,A,B;
    		me(dp,0,sizeof(dp));
    		scanf("%d %d %d",&n,&A,&B);
    		getchar();
    		scanf("%s",s+1);
    		dp[0][0][0][0]={1,0};
    		for(int i=0;i<=n;++i){
    			for(int j=0;i+j<=n;++j){
    				if(i+j==0) continue;
    				for(int a=0;a<A;++a){
    					for(int b=0;b<B;++b){
    						if(i && dp[i-1][j][a][b].fi) dp[i][j][(a*10+(s[i+j]-'0'))%A][b]={1,a};
    						if(j && dp[i][j-1][a][b].fi) dp[i][j][a][(b*10+(s[i+j]-'0'))%B]={2,b};
    					}		
    				}
    			}
    		}
    		int res=0;
    		for(int i=1;i<n;++i){
    			if(!dp[i][n-i][0][0].fi) continue;
    			if(abs(n-2*res)>=abs(n-2*i)) res=i;
    		}
    		if(!res){
    			puts("-1");
    			continue;
    		}
    		int a=0,b=0;
    		int x=res,y=n-res;
    		for(int i=n;i>=1;--i){
    			auto now=dp[x][y][a][b];
    			if(now.fi==1) ans[i]='R',a=now.se,x--;
    			else ans[i]='B',b=now.se,y--;
    		}
    		for(int i=1;i<=n;++i) printf("%c",ans[i]);
    		puts("");
    	}
        return 0;
    }
    
posted @ 2021-10-22 13:04  Rayotaku  阅读(48)  评论(0编辑  收藏  举报