目前计蒜客上面AC数量还是0,我也懒得交,估计CF Gym里面也该有这道,懒得找了。
题解:
今天的签到题。
把for循环换个思路考虑:
for var in range ( l , r ):
冷静一想不难发现等价于:
for var in range ( 1 , n ):
if(l <= var && var <= r)
于是实际上要求的就是有多少变量取值满足题意给的不等式链。
首先建立有向边,然后缩点,由于图太小了我就懒得写tarjan,直接用Floyd,显然同一个SCC里面的变量取值要一样,不同的构成一个DAG。
复杂度中 n n n 的次数显然就是 D A G DAG DAG 的点数。
考虑一下系数表示的东西是什么,这里比较抽象,表示的应该是所有可能的取值情况占了所有情况的几分之几。
渐进意义下强行让所有SCC不同不会改变答案,于是系数就是 合 法 拓 扑 序 个 数 / s c c C n t ! 合法拓扑序个数/sccCnt! 合法拓扑序个数/sccCnt! ,考虑所有点的大小关系还是挺显然的。
求拓扑序个数显然直接状压DP即可。
代码:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define cs const
using std::cerr;
using std::cout;
cs int N=21;
int n;
bool g[N][N];
int rt[N],bel[N];
ll dp[(1<<N)|7];
int ct=0,mp[1000];
int gid(int x){
return (mp[x]?mp[x]:mp[x]=++ct)-1;
}
void Main(){
std::ios::sync_with_stdio(false);
int m;std::cin>>m;
for(int re i=1;i<m;++i){
std::string tmp,v,l,r;
std::cin>>tmp>>v>>tmp>>l>>r;
int a=gid(v[0]),b=l[6],c=r[0];
if(b!='1')g[gid(b)][a]=true;
if(c!='n')g[a][gid(c)]=true;
}
for(int re k=0;k<ct;++k)
for(int re i=0;i<ct;++i)
for(int re j=0;j<ct;++j)
g[i][j]|=g[i][k]&g[k][j];
for(int re i=0;i<ct;++i){
bool tos=false;
for(int re j=0;j<i&&!tos;++j)
tos|=g[i][j]&&g[j][i];
if(!tos)rt[n++]=i;
}
for(int re i=0;i<n;++i)
for(int re j=0;j<n;++j){
if(g[rt[i]][rt[j]]&&i!=j)
bel[i]|=1<<j;
}
dp[0]=1;
for(int re s=0;s<(1<<n);++s)
for(int re i=0;i<n;++i)
if(!(s&(1<<i))&&(bel[i]|s)==s)
dp[s|(1<<i)]+=dp[s];
ll up=dp[(1<<n)-1],dn=1;
for(int re i=1;i<=n;++i)dn*=i;
ll g=std::__gcd(up,dn);
cout<<n<<" "<<up/g<<"/"<<dn/g<<"\n";
}
inline void file(){
#ifdef zxyoi
freopen("fygon.in","r",stdin);
#else
#ifndef ONLINE_JUDGE
freopen("fygon.in","r",stdin);
freopen("fygon.out","w",stdout);
#endif
#endif
}signed main(){file();Main();return 0;}