欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

JZOJ5711. 【北大夏令营2018模拟5.13】时间幻象

程序员文章站 2022-05-15 14:02:40
...

JZOJ5711. 【北大夏令营2018模拟5.13】时间幻象
JZOJ5711. 【北大夏令营2018模拟5.13】时间幻象

题目大意

要求出一个长度为n,且仅由ABCD四个字母组成的字符串,
通过给出的m种变化方式,以及任意交换相邻的两个,得出尽可能多的字符串。

题解

任意交换相邻的两个位置,也就是说当ABCD的个数确定的时候,就可以通关交换两个相邻的,弄出全排列。
其实,只需要记录ABC的个数就可以了,D的个数是可以直接算出来的。
n只有30,估算一下最多的状态数只有不到6000,那么考虑转移,也就是只有m*状态数。
这样以ABC的数量为点,根据给出的条件连有向边。
现在题目就变成了求图中的最长路,
就先用tarjan缩点,对于一个强连通分量里面是所有点,可以从任意一个位置进去,然后走完整个环之后,再从任意一个位置出来,根据拓扑序求出最长路就好了。

code

#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#define ll long long
#define N 150003 
#define M 33
#define P putchar
#define G getchar
using namespace std;
char ch;
void read(int &n)
{
    n=0;
    ch=G();
    while((ch<'0' || ch>'9') && ch!='-')ch=G();
    ll w=1;
    if(ch=='-')w=-1,ch=G();
    while('0'<=ch && ch<='9')n=(n<<3)+(n<<1)+ch-'0',ch=G();
    n*=w;
}

int ti,dfn[N],low[N],z[N],g[N],cnt,ta;
int lst[N],nxt[N],to[N],tot;
int lst_[N],nxt_[N],to_[N],tot_;
int n,m,t1[5],t2[5],t[5],id[M][M][M],w,tt;
int q[N],d[N],l,r,x;
int s[M][M],sum[M];
long long f[N],V[N],F[N],ans;
bool bz[N];

void tarjan(int x)
{
    ti++;
    dfn[x]=low[x]=ti;
    bz[x]=0;
    ta++;
    z[ta]=x;
    for(int i=lst[x];i;i=nxt[i])
    {
        if(dfn[to[i]]==0)
        {
            tarjan(to[i]);
            low[x]=min(low[x],low[to[i]]);
        }
        else if(!bz[to[i]])low[x]=min(low[x],dfn[to[i]]);
    }
    if(low[x]==dfn[x])
    {
        for(cnt++;z[ta]!=x && ta;ta--)F[g[z[ta]]=cnt]+=V[z[ta]],bz[z[ta]]=1;
        F[g[z[ta]]=cnt]+=V[z[ta]],bz[z[ta]]=1;
        ta--;
    }
}

void ins(int x,int y)
{
    nxt[++tot]=lst[x];
    to[tot]=y;
    lst[x]=tot;
}

void ins_(int x,int y)
{
    nxt_[++tot_]=lst_[x];
    to_[tot_]=y;
    lst_[x]=tot_;
}

void re()
{
    memset(t1,0,sizeof(t1));
    memset(t2,0,sizeof(t2));
    for(ch=G();ch<'A' || ch>'D';ch=G());
    for(;'A'<=ch && ch<='D';ch=G())t1[ch-'A']++;
    for(ch=G();ch<'A' || ch>'D';ch=G());
    for(;'A'<=ch && ch<='D';ch=G())t2[ch-'A']++;
    for(int i=0;i<5;i++)t[i]=t2[i]-t1[i];
}

void pre()
{
    for(register int i=1;i<M;i++)
    {
        int t=i;
        for(register int j=2;j<M;j++)
        {
            s[i][j]+=s[i-1][j];
            for(;t%j==0;t=t/j)s[i][j]++;
        }
        s[i][t]++;
    }
}

ll ksm(ll x,int y)
{
    ll s=1;
    for(;y;y>>=1,x=x*x)
        if(y&1)s=s*x;
    return s;
}

void get()
{
    for(register int i=0;i<=n;i++)
        for(register int j=0;j+i<=n;j++)
            for(register int k=0;k+i+j<=n;k++)
            {
                V[id[i][j][k]]=1;
                for(int w=2;w<M;w++)
                    V[id[i][j][k]]*=ksm(w,s[n][w]-s[i][w]-s[j][w]-s[k][w]-s[n-i-j-k][w]);
            }
}

int main()
{
    freopen("return.in","r",stdin);
    freopen("return.out","w",stdout);

    pre();read(n);
    for(register int i=0;i<=n;i++)
        for(register int j=0;j+i<=n;j++)
            for(register int k=0;k+i+j<=n;k++)
                id[i][j][k]=++w;
    for(read(m),get();m;m--)
    {
        re();
        for(register int i=0;i<=n;i++)
            if(t[0]+i<=n && i>=t1[0])
            for(register int j=0;j+i<=n;j++)
                if(t[1]+j<=n && j>=t1[1])
                for(register int k=0;k+i+j<=n;k++)
                    if(t[2]+k<=n && k>=t1[2])
                    {
                        tt=n-i-j-k;
                        if(t[3]+tt>n || tt<t1[3])continue;
                        ins(id[i][j][k],id[i+t[0]][j+t[1]][k+t[2]]);
                    }       
    }

    memset(bz,1,sizeof(bz));
    for(register int i=1;i<=w;i++)
        if(dfn[i]==0)tarjan(i);

    for(register int i=1;i<=w;i++)
        for(register int j=lst[i];j;j=nxt[j])
            if(g[i]!=g[to[j]])ins_(g[i],g[to[j]]),d[g[to[j]]]++;

    for(register int i=1;i<=w;i++)
        if(d[i]==0)q[++r]=i,f[i]=0;

    for(l=0;l<r;)
    {
        f[x=q[++l]]+=F[x];
        for(register int i=lst_[x];i;i=nxt_[i])
        {
            f[to_[i]]=max(f[to_[i]],f[x]);
            d[to_[i]]--;
            if(d[to_[i]]==0)q[++r]=to_[i];
        }
        ans=max(ans,f[x]);
    }
    printf("%lld",ans);

    return 0;
}
相关标签: tarjan