【折半搜索】AtCoder Grand Contest 026 String Coloring

2 篇文章 0 订阅

题意:

给出一个字符串s。
给这个串的每个位置染上红/蓝色,要求正向读每个染成红色的字符所组成的字符串s1,与反向读每个染成蓝色的字符所组成的字符串s2,满足s1=s2


分析:

由于N很小,我们可以考虑折半搜索。先搜前一半,用字符串hash把蓝、红两种颜色的字符串表示出来,存入一个map里面,再搜后一半,还是用字符串hash求出方案数。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<map>
#define SF scanf
#define PF printf
#define MAXN 350
using namespace std;
typedef unsigned long long ll;
int n;
char s[MAXN];
map<pair<ll,ll> ,ll> used[MAXN][MAXN];
ll ans;
void dfs1(int x,ll sum1,ll sum2,int len1,int len2){
    if(x==n){
        used[len1][len2][make_pair(sum1,sum2)]++;
        return ;
    }
    dfs1(x+1,sum1*131+(ll)(s[x]-'a'+1),sum2,len1+1,len2);
    dfs1(x+1,sum1,sum2*131+(ll)(s[x]-'a'+1),len1,len2+1);
}
void dfs2(int x,ll sum1,ll sum2,int len1,int len2){
    if(x==n-1){
        ans+=used[len1][len2][make_pair(sum1,sum2)];
        return ;
    }
    dfs2(x-1,sum1*131+(ll)(s[x]-'a'+1),sum2,len1+1,len2);
    dfs2(x-1,sum1,sum2*131+(ll)(s[x]-'a'+1),len1,len2+1);
}
int main(){
    SF("%d",&n); 
    SF("%s",s);
    dfs1(0,0,0,0,0); 
    dfs2(2*n-1,0,0,0,0);
    PF("%llu",ans);
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值