SWERC 2017 H Kabobs

2 篇文章 0 订阅
2 篇文章 0 订阅

这题就是暴力暴力暴力。。。

暴力记每个规则匹配到哪里

可以脑补一下为什么正确:

1.x60x+2 x=4 时取到 max=1048576

2. 一旦失配立刻就跳回去,所以除了 x=2 ,其他时候根本卡不满

直接预处理状态及转移然后暴力暴力暴力就过了

#include<bits/stdc++.h>
#define mod 10000000
#define maxn 110
#define getp(x) (__builtin_ctzll(x))
using namespace std;
typedef unsigned long long ull;
typedef pair<int,int> par;
int n,bg[maxn],tp,a[maxn],vbg[maxn];
char A[maxn],R[maxn];
ull bgS,flg=0;
struct Hash{
    ull v[1101000];
    int head[100100],id[1101000],nxt[1101000],ptr;
    int count(ull a){
        int x=a%10007;
        for(int y=head[x];y;y=nxt[y])if(v[y]==a)return true;
        return false;
    }
    int& operator[](ull a){
        int x=a%10007;
        for(int y=head[x];y;y=nxt[y])if(v[y]==a)return id[y];
        v[++ptr]=a,nxt[ptr]=head[x],head[x]=ptr;
        return id[ptr];
    }
}st;
vector<ull>v;
vector<vector<par> >trans;
void print(ull S){
    printf("(");
    for(int i=0;i<60;++i)if(S>>i&1)printf("%d ",i);
    printf(")");
}
void get_trans(ull S){
    map<int,int>nxt;
    int vis[200]={0};
    for(int i=0;i<v.size();++i){
        trans.push_back(vector<par>());
        nxt.clear();
        ull nS=0,S=v[i];
        for(int i=0;i<60;++i)if(S>>i&1)
            nS|=1ull<<bg[i];
        int cnt=0;
        for(int i=0;i<60;++i)if(S>>i&1)
            vis[R[i]]=vis[R[bg[i]]]=1;
        for(int i=0;A[i];i++)if(vis[A[i]]){
            ull nwS=0;
            for(int j=0;j<60;++j)if(S>>j&1){
                int pos=j,np=a[j];
                if(R[pos]!=A[i])
                    pos=bg[pos];
                if(R[pos]==A[i]){
                    if(R[pos+1]=='|'||R[pos+1]==0)pos=vbg[pos];
                    else if(R[pos+1]=='>')pos+=2;
                    else pos++;
                } 
                nwS|=1ull<<pos;
            }
            if(!st.count(nwS)){
                st[nwS]=v.size();
                v.push_back(nwS);
            }
            nxt[st[nwS]]++;
        } else cnt++;
        if(!st.count(nS)){
            st[nS]=v.size();
            v.push_back(nS);
        }
        nxt[st[nS]]+=cnt;
        for(auto s:nxt)trans[i].push_back(s);
        for(int i=0;i<60;++i)if(S>>i&1)
            vis[R[i]]=vis[R[bg[i]]]=0;
    }
}
bool pd(ull S){
    for(int i=0;i<60;++i)if(S>>i&1)
        if(vbg[i]!=bg[i])return 0;
    return 1;
}
int main(){
    scanf("%d%s%s",&n,A,R);
    memset(bg,-1,sizeof(bg));
    memset(vbg,-1,sizeof(vbg));
    bg[0]=0,bgS|=1ull<<0,flg=0;
    for(int i=0;R[i];i++){
        if(R[i]=='|')
            tp++,bg[i+1]=i+1,vbg[i+1]=i+1,bgS|=1ull<<i+1;
        else if(R[i]=='>')
            bg[i+1]=i+1;
        else if(bg[i]==-1)bg[i]=bg[i-1];
        if(vbg[i]==-1)vbg[i]=vbg[i-1];
    }
    st[bgS]=0,v.push_back(bgS);
    get_trans(bgS); 
    ull dp[2][v.size()];
    int p=0,np=1;
    for(int i=0;i<v.size();++i)dp[0][i]=dp[1][i]=0;
    dp[np][0]=1;
    for(int i=1;i<=n;++i,swap(p,np)){
        for(int j=0;j<v.size();++j)if(dp[np][j]){
            for(auto k:trans[j])
                dp[p][k.first]+=dp[np][j]*k.second;
            dp[np][j]=0;
        }
        for(int j=0;j<v.size();++j)if(dp[p][j])
            dp[p][j]%=mod;
    }
    ull ans=0;
    for(int i=0;i<v.size();++i)if(pd(v[i]))
        ans+=dp[np][i];
    printf("%d",ans%mod);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值