結果

問題 No.1116 Cycles of Dense Graph
コンテスト
ユーザー vwxyz
提出日時 2021-09-15 20:16:03
言語 PyPy3
(7.3.15)
結果
WA  
実行時間 -
コード長 5,238 bytes
コンパイル時間 313 ms
コンパイル使用メモリ 82,304 KB
実行使用メモリ 93,176 KB
最終ジャッジ日時 2024-06-28 21:15:30
合計ジャッジ時間 21,995 ms
ジャッジサーバーID
(参考情報)
judge2 / judge4
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 3
other AC * 32 WA * 1 TLE * 5
権限があれば一括ダウンロードができます

ソースコード

diff #
raw source code

import bisect
import copy
import decimal
import fractions
import functools
import heapq
import itertools
import math
import random
import sys
from collections import Counter,deque,defaultdict
from functools import lru_cache,reduce
from heapq import heappush,heappop,heapify,heappushpop,_heappop_max,_heapify_max
def _heappush_max(heap,item):
    heap.append(item)
    heapq._siftdown_max(heap, 0, len(heap)-1)
def _heappushpop_max(heap, item):
    if heap and item < heap[0]:
        item, heap[0] = heap[0], item
        heapq._siftup_max(heap, 0)
    return item
from math import degrees, gcd as GCD
read=sys.stdin.read
readline=sys.stdin.readline
readlines=sys.stdin.readlines

def Extended_Euclid(n,m):
    stack=[]
    while m:
        stack.append((n,m))
        n,m=m,n%m
    if n>=0:
        x,y=1,0
    else:
        x,y=-1,0
    for i in range(len(stack)-1,-1,-1):
        n,m=stack[i]
        x,y=y,x-(n//m)*y
    return x,y

class MOD:
    def __init__(self,p,e=1):
        self.p=p
        self.e=e
        self.mod=self.p**self.e

    def Pow(self,a,n):
        a%=self.mod
        if n>=0:
            return pow(a,n,self.mod)
        else:
            assert math.gcd(a,self.mod)==1
            x=Extended_Euclid(a,self.mod)[0]
            return pow(x,-n,self.mod)

    def Build_Fact(self,N):
        assert N>=0
        self.factorial=[1]
        self.cnt=[0]*(N+1)
        for i in range(1,N+1):
            ii=i
            self.cnt[i]=self.cnt[i-1]
            while ii%self.p==0:
                ii//=self.p
                self.cnt[i]+=1
            self.factorial.append((self.factorial[-1]*ii)%self.mod)
        self.factorial_inve=[None]*(N+1)
        self.factorial_inve[-1]=self.Pow(self.factorial[-1],-1)
        for i in range(N-1,-1,-1):
            ii=i+1
            while ii%self.p==0:
                ii//=self.p
            self.factorial_inve[i]=(self.factorial_inve[i+1]*ii)%self.mod

    def Fact(self,N):
        if N<0:
            return 0
        return self.factorial[N]*pow(self.p,self.cnt[N],self.mod)%self.mod

    def Fact_Inve(self,N):
        if self.cnt[N]:
            return None
        return self.factorial_inve[N]

    def Comb(self,N,K,divisible_count=False):
        if K<0 or K>N:
            return 0
        retu=self.factorial[N]*self.factorial_inve[K]*self.factorial_inve[N-K]%self.mod
        cnt=self.cnt[N]-self.cnt[N-K]-self.cnt[K]
        if divisible_count:
            return retu,cnt
        else:
            retu*=pow(self.p,cnt,self.mod)
            retu%=self.mod
            return retu

def Zip(lst):
    unzip=sorted(list(set(lst)))
    zip={x:i for i,x in enumerate(unzip)}
    return zip,unzip

class UnionFind:
    def __init__(self,n):
        self.n=n
        self.parents=[-1]*n

    def Find(self,x):
        stack=[]
        while self.parents[x]>=0:
            stack.append(x)
            x=self.parents[x]
        for y in stack:
            self.parents[y]=x
        return x

    def Union(self,x,y):
        x=self.Find(x)
        y=self.Find(y)
        if x==y:
            return
        if self.parents[x]>self.parents[y]:
            x,y=y,x
        self.parents[x]+=self.parents[y]
        self.parents[y]=x

    def Size(self,x):
        return -self.parents[self.Find(x)]

    def Same(self,x,y):
        return self.Find(x)==self.Find(y)

    def Members(self,x):
        root = self.Find(x)
        return [i for i in range(self.n) if self.Find(i)==root]

    def Roots(self):
        return [i for i, x in enumerate(self.parents) if x<0]

    def Group_Count(self):
        return len(self.Roots())

    def All_Group_Members(self):
        group_members = defaultdict(list)
        for member in range(self.n):
            group_members[self.Find(member)].append(member)
        return group_members

    def __str__(self):
        return '\n'.join(f'{r}: {m}' for r, m in self.All_Group_Members().items())

N,M=map(int,readline().split())
edges=[]
for _ in range(M):
    a,b=map(int,readline().split())
    a-=1;b-=1
    edges.append((a,b))
ans=0
mod=998244353
MD=MOD(mod)
MD.Build_Fact(N)
@lru_cache(maxsize=None)
def f(n,c):
    s=0
    if c>=2:
        s+=MD.Fact(c-1)
    elif n!=N-1:
        s+=1
    for i in range(c+1,n+1):
        s+=MD.Comb(n-c,i-c)*MD.Fact(i-1)
        s%=mod
    s*=pow(2,c-1,mod)
    s%=mod
    return s
for i in range(3,N+1):
    ans+=MD.Comb(N,i)*MD.Fact(i-1)
    ans%=mod
ans*=MD.Pow(2,-1)
ans%=mod
for bit in range(1,1<<M):
    points=[]
    pop_cnt=0
    for i in range(N):
        if bit>>i&1:
            a,b=edges[i]
            points.append(a)
            points.append(b)
            pop_cnt+=1
    zip,unzip=Zip(points)
    l=len(zip)
    UF=UnionFind(l)
    cnt=[0]*l
    cycle=False
    for i in range(N):
        if bit>>i&1:
            a,b=edges[i]
            UF.Union(zip[a],zip[b])
            cnt[zip[a]]+=1
            cnt[zip[b]]+=1
    for c in cnt:
        if c>=3:
            continue
    if cnt.count(2)==l and UF.Group_Count()==1:
        if pop_cnt%2==0:
            ans+=1
        else:
            ans-=1
    else:
        if pop_cnt%2==0:
            ans+=f(N-pop_cnt,UF.Group_Count())
        else:
            ans-=f(N-pop_cnt,UF.Group_Count())
    ans%=mod
print(ans)
0