zoukankan      html  css  js  c++  java
  • [Aizu2993]Invariant Tree

    若$(i,j)in E$,实际上会不断推出$(p_{i},p_{j})in E,(p_{p_{i}},p_{p_{j}})in E,...$

    考虑将$i$向$p_{i}$连边得到了一张(由若干个环组成的)有向图,则$(i,j)in E$有以下两个必要条件:

    1.若$i$和$j$在同一个环中,则对应环长$l$必须恰为2

    设$d$为$i$和$j$的环上距离,则环上距离为$d$的点对间都有边,则这$l$个点之间至少有$l$条边(特别的,若$l=2$时有重边),显然会产生环

    2.若$i$和$j$不在同一个环中,假设两者对应环长分别为$u$和$v$,则$umid v$或$vmid u$

    (不妨假设$ule v$)设$d=gcd(u,v)$,则与$i$环上距离$equiv $与$j$环上距离$(mod d)$的点对间都有边,也即这$u+v$个点之间至少有$frac{uv}{d}$条边,二若$d<u$则$frac{uv}{d}ge 2vge u+v$,显然会产生环

    另外,根据上述分析还可以得到对于$umid v$的情况,这两个环之间会恰有$v$条边

    接下来,将图转换到环上,即对所有环之间连边,两环之间有边当且仅当存在一个点对之间有边

    继续分析第2类边,还可以得到以下三个个必要条件:

    1.两个环之间至多存在一条边

    注意到两条边所产生的边必然不同,将两者边数相加即为$2vge u+v$,显然会产生环

    2.一个环至多向一个环长严格小于其的环连边

    假设其环长为$v$,严格小于其的环长为$u_{1}$和$u_{2}$,则边数为$2v$而点数为$v+u_{1}+u_{2}le 2v$,显然会产生环

    3.对于环长相同的点,其内部的边不会产生环

    假设环长为$l$,产生的简单环环长为$l'$,则点数和边数均为$ll'$,显然会产生环

    根据上述必要条件,可以得到以下推论:环之间的边也不存在环,进而也即是一棵树

    以其中环长最小的点为根,得到一棵有根树,那么树上每一条边父亲的环大小必然不超过儿子,进而实际上的边数即其儿子的环大小,总边数也即$n-$根节点的环大小

    接下来,需要对是否存在大小为1,2的环分类讨论:

    1.若存在大小为1的环,显然以某个大小为1的环为根,再为其余环找一个父亲,此时已经存在$n-1$条边,即不会存在第1类边,并且可以证明:1.此时的原图是一棵树;2.每一条边实际上还对应于父亲的环大小种方案

    换言之,也即求所有这样的树(根确定)每一个非根节点父亲环大小乘积和

    考虑求出每一种环长对答案的贡献并相乘,而对于其中大小为$i$的环,假设有$cnt$个,令$w$为环长是其约数的环大小和$,f(n,m)$为$n$个点$m$个根的森林数,则贡献为$sum_{m=1}^{cnt}w^{m}i^{cnt-m}f(cnt,m)$

    根据purfer序列,可以得到$f(n,m)={n-1choose m-1}n^{n-m-1}$,代入后即为$w(w+icdot cnt)^{cnt-1}$

    2.若不存在大小为1的环且存在大小为2的环,显然以某个大小为2的环为根,并需要再挑一个大小为2的环在其中连第1类边来保证环的性质,也即在第1种情况的基础上乘上大小为2的环个数即可

    3.若不存在大小为1或2的环,此时显然无解

    最终,时间复杂度为$o(nlog n)$(统计$w$),可以通过

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 300005
     4 #define mod 998244353
     5 #define ll long long
     6 vector<int>v[N];
     7 int n,s,ans,a[N],vis[N],cnt[N];
     8 int qpow(int n,int m){
     9     int s=n,ans=1;
    10     while (m){
    11         if (m&1)ans=(ll)ans*s%mod;
    12         s=(ll)s*s%mod;
    13         m>>=1;
    14     }
    15     return ans;
    16 }
    17 void dfs(int k){
    18     if (vis[k])return;
    19     s++,vis[k]=1,dfs(a[k]);
    20 }
    21 int main(){
    22     scanf("%d",&n);
    23     for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    24     for(int i=1;i<=n;i++)
    25         if (!vis[i])s=0,dfs(i),cnt[s]++;
    26     ans=1; 
    27     for(int i=1;i<=n;i++)
    28         for(int j=(i<<1);j<=n;j+=i)v[j].push_back(i);
    29     if ((!cnt[1])&&(!cnt[2])){
    30         printf("0
    ");
    31         return 0;
    32     }
    33     int st=2;
    34     if (cnt[1]){
    35         if (cnt[1]!=1)ans=qpow(cnt[1],cnt[1]-2);
    36     }
    37     else{
    38         st=3;
    39         ans=(ll)qpow(cnt[2],cnt[2]-1)*qpow(2,cnt[2]-1)%mod;
    40     }
    41     for(int i=st;i<=n;i++){
    42         if (!cnt[i])continue;
    43         int w=0,s=0;
    44         for(int j=0;j<v[i].size();j++)w+=v[i][j]*cnt[v[i][j]];
    45         ans=(ll)ans*w%mod*qpow(w+i*cnt[i],cnt[i]-1)%mod;
    46     }
    47     printf("%d
    ",ans);
    48     return 0;
    49 } 
    View Code
  • 相关阅读:
    Unix/Linux笔记全集
    深入浅出-变长参数
    基于 SSH 的远程操作以及安全,快捷的数据传输<转>
    面向对象的特性—— 封装
    wpf 窗体翻页效果
    wpf控件拖动
    Wpf 导出CSV文件
    wpf 导出Excel
    Wpf Button 样式
    wpf简单进度条
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/15475341.html
Copyright © 2011-2022 走看看