AGC008E Next or Nextnext

Posted cjoiershiina-mashiro

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AGC008E Next or Nextnext相关的知识,希望对你有一定的参考价值。

Link
如果我们(i ightarrow p_i)建边,那么最后会得到一些有向环。
对于上述的每一个环,如果我们(i ightarrow a_i)建边,那么此时(a_i)(i)在顺时针方向下的第(1operatorname{or}2)个点,也就是(a_i=p_ivee a_i=p_{p_i})
那么此时有四种情况:
(a_i=p_i),那么这个环不变。
(a_i=p_{p_i}),那我们对环长的奇偶性分开讨论。
若环长为奇数,那么这个环变成元素相同的另一个环。
若环长为偶数,那么这个环会被拆成两个环。
否则部分(a_i=p_i),部分(a_i=p_{p_i}),那么这个环会被拆成一个环和若干个指向环的链构成的基环内向树。
现在我们只有(i ightarrow a_i)建出来的图,所以我们倒过来考虑。
如果这不是由若干个环和基环内向树构成的森林,那么答案为(0)
求出对于任意一个(l),有多少个环长度为(l),然后利用do求出对于一个环长而言的方案数,最后再根据乘法原理乘起来就好了。
假如现在长度为(l),设(f_i)表示有(i)个长度为(l)的环的方案数,那么有:

[f_j= egin{cases} 1&j=01+[i e1wedge2 mid i]&j=1i(j-1)f_{j-2}+f_if_{j-1}& ext{otherwise} end{cases} ]

然后就只需要考虑基环内向树的方案数了。
我们把每条链(包括环上的点)单独拿出来,那么这个环会被剖成很多份。
假设一条链长为(l),从这条链顺时针的一段环的长度为(d),那么:
(dle l),则答案为(0);若(d=l),则方案数为(1);若(d>l),则方案数为(2)
然后根据乘法原理把基环内向树的答案和环的答案乘在一起就好了。

#include<cstdio>
#include<cctype>
const int N=100007,P=1000000007;
int a[N],deg[N],vis[N],pre[N],cnt[N],f[N];
int read(){int x=0,c=getchar();while(isspace(c))c=getchar();while(isdigit(c))(x*=10)+=c&15,c=getchar();return x;}
int add(int a,int b){return a+=b-P,a+(a>>31&P);}
int mul(int a,int b){return 1ll*a*b%P;}
int main()
{
    int n=read(),ans=1;
    for(int i=1;i<=n;++i) ++deg[a[i]=read()];
    for(int i=1,p;(p=i)<=n;++i)
    {
	if(deg[i]>2) return puts("0"),0;
	if(deg[i]<2||vis[i]) continue;
	do
	{
	    if(vis[p]) return puts("0"),0;
	    vis[p]=1,pre[a[p]]=p,p=a[p];
	}while(p^i);
    }
    for(int i=1,p,l1,l2;i<=n;++i)
	if(!deg[i])
	{
	    for(p=i,l1=0,l2=0;!vis[p];p=a[p]) vis[p]=1,++l1;
	    do ++l2,p=pre[p]; while(deg[p]^2);
	    if(l1<l2) ans=add(ans,ans); else if(l1>l2) return puts("0"),0;
	}
    for(int i=1;i<=n;++i)
	if(!vis[i])
	{
	    int p=i,l=0;
	    do ++l,p=a[p],vis[p]=1; while(p^i);
	    ++cnt[l];
	}
    for(int i=1;i<=n;ans=mul(ans,f[cnt[i++]]))
    {
	f[0]=1,f[1]=1+(i^1&&i&1);
	for(int j=2;j<=cnt[i];++j) f[j]=add(mul(i,mul(j-1,f[j-2])),mul(f[1],f[j-1]));
    }
    printf("%d",ans);
}

以上是关于AGC008E Next or Nextnext的主要内容,如果未能解决你的问题,请参考以下文章

[agc008E]Next or Nextnext-[dp+思考题]

@atcoder - AGC008E@ Next or Nextnext

AGC008_E Next or Nextnext

agc019f - Yes or No

agc019FYes or No

agc015D A or...or B Problem