[agc008E]Next or Nextnext-[dp+思考题]
Posted coco-night
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[agc008E]Next or Nextnext-[dp+思考题]相关的知识,希望对你有一定的参考价值。
Description
Solution
然后我谈下个人理解。由于我们的两个条件只要任意满足,则在p的图中i有两种连边法:i->p[i],i->p[p[i]]。
我们考虑在a的图中i->a[i]。可得我们要把p图塞到a图里。
具体分析看题解吧,题解图画的很清晰呀。然后。。就各种dp+乱搞了。
Code
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> using namespace std; typedef long long ll; const int mod=1e9+7; int n,x; int a[100010]; int in[100010],col[100010],cir[100010]; int len[100010],cnt[100010]; ll dp[100010],ans=1; int main() { scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%d",&a[i]); for (int i=1;i<=n;i++) { in[a[i]]++; x=i;while (!col[x]) {col[x]=i;x=a[x];} if (col[x]!=i) continue; while (!cir[x]) {cir[x]=i;x=a[x];} } for (int i=1;i<=n;i++) if ((cir[i]&&in[i]>2)||(!cir[i]&&in[i]>1)) return printf("0"),0; int js; for (int i=1;i<=n;i++) { if (in[i]) continue; x=i;js=0; while (!cir[x]) {js++;x=a[x];} len[x]=js; } int _len,fir,st,id; for (int i=1;i<=n;i++) { if (!cir[i]) continue; x=i; _len=fir=st=id=0; for(;cir[x];x=a[x]) { id++;cir[x]=0; if(len[x]) { if (!fir){fir=st=id;_len=len[x];} else { ans=ans*((len[x]<id-st)+(len[x]<=id-st))%mod; if (!ans) return printf("0"),0;st=id; } } } if (fir) { ans=ans*((_len<id+fir-st)+(_len<=id+fir-st))%mod; if (!ans)return printf("0"),0; } else cnt[id]++; } for (int i=1;i<=n;i++) { if (!cnt[i]) continue; dp[0]=1; if (i>1&&i%2) for (int j=1;j<=cnt[i];j++) { dp[j]=dp[j-1]*2%mod; if (j>1) dp[j]=(dp[j]+dp[j-2]*(j-1)*i%mod)%mod; } else for (int j=1;j<=cnt[i];j++) { dp[j]=dp[j-1]; if (j>1) dp[j]=(dp[j]+dp[j-2]*(j-1)*i%mod)%mod; } ans=ans*dp[cnt[i]]%mod; if (!ans) return printf("0"),0; } cout<<ans; }
以上是关于[agc008E]Next or Nextnext-[dp+思考题]的主要内容,如果未能解决你的问题,请参考以下文章
[agc008E]Next or Nextnext-[dp+思考题]