• ZR265 归来


    链接:http://zhengruioi.com/problem/265

    第一种操作使得你可以任意访问该字符串的全排列

    因此可以得到(frac{n!}{a!*b!*c!*d!})种方案

    然后把每一组(a,b,c,d)看成一个节点的话

    第二种操作就是在这些节点中连边

    最终答案就是一个最长路

    tarjan缩点+dp即可

    #include<bits/stdc++.h>
    #define M 33
    #define N 3300000
    #define eps 1e-7
    #define inf 1e9+7
    #define db double
    #define ll long long
    #define ldb long double
    #define ull unsigned long long
    using namespace std;
    inline ll read()
    {
    	char ch=0;
    	ll x=0,flag=1;
    	while(!isdigit(ch)){ch=getchar();if(ch=='-')flag=-1;}
    	while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0',ch=getchar();}
    	return x*flag;
    }
    struct node{ll a,b,c,d;}p[N];
    struct edge{ll to,nxt;}e[N];
    struct link{ll x,y;}lk[N];
    ll num,head[N];
    inline void add(ll x,ll y)
    {
    	//if(x==y)return;
    	e[++num]={y,head[x]};head[x]=num;
    }
    char S[N],T[N];
    ll n,m,size,w[N],v[N],C[M][M],id[M][M][M][M];
    ll cal(ll a,ll b,ll c,ll d){return C[n][a]*C[n-a][b]*C[n-a-b][c];}
    stack<ll>st;
    bool in_stack[N];
    ll times,bel_cnt,dp[N],dfn[N],low[N],bel[N];
    void tarjan(ll x)
    {
    	dfn[x]=low[x]=++times;
    	st.push(x);in_stack[x]=true;
    	for(ll i=head[x];i!=-1;i=e[i].nxt)
    	{
    		ll to=e[i].to;
    		if(!dfn[to])tarjan(to),low[x]=min(low[x],low[to]);
    		else if(in_stack[to])low[x]=min(low[x],dfn[to]);
    	}
    	if(dfn[x]==low[x])
    	{
    		ll t=x;
    		bel_cnt++;
    		do
    		{
    			t=st.top();st.pop();
    			in_stack[t]=false;
    			bel[t]=bel_cnt;v[bel_cnt]+=w[t];
    		}while(t!=x);
    	}
    }
    ll dfs(ll x)
    {
    	if(dp[x]!=-1)return dp[x];
    	dp[x]=v[x];
    	for(ll i=head[x];i!=-1;i=e[i].nxt)
    	{
    		ll to=e[i].to;
    		dp[x]=max(dp[x],dfs(to)+v[x]);
    	}
    	return dp[x];
    }
    int main()
    {
    	n=read();m=read();
    	num=-1;memset(head,-1,sizeof(head));
    	for(ll i=0;i<=n;i++)
    	{
    		C[i][0]=1;
    		for(ll j=1;j<=i;j++)C[i][j]=C[i-1][j-1]+C[i-1][j];
    	}
    	for(ll a=0;a<=n;a++)for(ll b=0;a+b<=n;b++)for(ll c=0;a+b+c<=n;c++)
    	{
    		ll d=n-a-b-c;
    		id[a][b][c][d]=++size;w[size]=cal(a,b,c,d);
    	}
    	for(ll i=1;i<=m;i++)
    	{
    		scanf("%s",S);scanf("%s",T);
    		ll len=max(strlen(S),strlen(T));
    		ll sa=0,sb=0,sc=0,sd=0,ta=0,tb=0,tc=0,td=0;
    		for(ll k=0;k<len;k++)
    		{
    			sa+=(S[k]=='A');
    			sb+=(S[k]=='B');
    			sc+=(S[k]=='C');
    			sd+=(S[k]=='D');
    			ta+=(T[k]=='A');
    			tb+=(T[k]=='B');
    			tc+=(T[k]=='C');
    			td+=(T[k]=='D');
    		}
    		for(ll a=sa;a<=n;a++)for(ll b=sb;a+b<=n;b++)for(ll c=sc;a+b+c<=n;c++)
    		{
    			ll d=n-a-b-c;
    			if(d<sd)continue;
    			add(id[a][b][c][d],id[a+ta-sa][b+tb-sb][c+tc-sc][d+td-sd]);
    		}
    	}
    	for(ll i=1;i<=size;i++)if(!dfn[i])tarjan(i);
    	ll cnt=0;
    	for(ll x=1;x<=size;x++)
    	for(ll i=head[x];i!=-1;i=e[i].nxt)
    	{
    		ll to=e[i].to;
    		if(bel[x]!=bel[to])lk[++cnt]=(link){bel[x],bel[to]};
    	}
    	num=-1;memset(head,-1,sizeof(head));
    	for(ll i=1;i<=cnt;i++)add(lk[i].x,lk[i].y);
    	ll ans=0;
    	memset(dp,-1,sizeof(dp));
    	for(ll i=1;i<=bel_cnt;i++)ans=max(ans,dfs(i));
    	printf("%lld",ans);
    	return 0;
    }
    
  • 相关阅读:
    JavaScriptCore框架介绍
    可执行程序加载到内存的过程
    阿里云服务器怎么更换系统盘
    什么是A记录  域名
    宝塔服务器管理助手Linux面版-使用教程
    虚拟主机、VPS以及云主机的区别和对比
    怎样选择一个好的虚拟主机
    解Linux SSH命令大全,新手必看SSH命令
    虚拟主机,VPS,云主机之间的区别?
    云服务器和虚拟主机的区别:
  • 原文地址:https://www.cnblogs.com/Creed-qwq/p/13727788.html
Copyright © 2020-2023  润新知