LoginSignup
2
4

More than 3 years have passed since last update.

競プロであったら嬉しいと思ったスニペットのまとめ

Last updated at Posted at 2019-06-27

はじめに

競プロやっててほしいなと思ったスニペットとかをまとめて行くつもりです。そのうち増えていく予定です。
メインがPythonサブがC++なので、基本Pythonで書いていきますが余裕があったらC++のコードも足して行こうと思います。

また、全境界条件等検討できているとは限らないので責任はおえません。あしからず。

GCD(最大公約数),LCM(最小公倍数)

最大公約数はユークリッドの互除法によって構成します。LCMは2数の積/最大公約数です。
2数に関してのGCD及びLCMを繰り返すことで配列で与えた整数群に関してのGCD,LCMを計算します。

def gcd_core(a, b):
    if b == 0:
        return a
    else:
        return gcd_core(b, a % b)

def gcd(arr):
    g = gcd_core(arr[0], arr[1])
    for i in range(2, len(arr)):
        g = gcd_core(g, arr[i])
    return g

def lcm_core(a,b):
    g = gcd_core(a,b)
    return (a*b)//g

def lcm(arr):
    l = lcm_core(arr[0],arr[1])
    for i in range(2,len(arr)):
        l = lcm_core(l,arr[i])
    return l

Union-Find木(連結要素)

UF木です。経路圧縮などは根をたどるときのつなぎ直ししか入れていないため、もっと最適化が必要な場面が出てくるかもしれません。indep()で連結要素の数を数えることができます。ノードが1 indexから始まる場合はn+1でインスタンスを作成して、ノード0を捨てます。

class uf_tree():

    def __init__(self,n):
        self.n = n
        self.par = [i for i in range(n)]

    def indep(self):
        dep =0
        for i in range(self.n):
            if i == self.par[i]:
                dep += 1

        return dep

    def unite(self,child,mas):
        if self.root(child) == self.root(mas):
            return
        else:
            self.par[self.root(child)] = self.root(mas)

    def root(self,i):
        if self.par[i] == i:
            return i
        else:
            self.par[i] = self.root(self.par[i])
            return self.par[i]

    def same(self,x,y):
        if self.root(x) == self.root(y):
            return True
        else:
            return False

素因数分解(ためしわり)

返り値はディクショナリです。
{因数:べき数}の形になっています。
素数のときはからのディクショナリが返ってきます。

def factorize(N):
    up = int(np.sqrt(N))+2
    out = {}

    for i in range(2,up):
        if N%i == 0:
            temp = N
            count = 0
            while(True):
                N = N//i
                count += 1
                if N%i != 0:
                    break
            out[i] = count
        else:
            continue
    return out
print(factorize(60))
print(factorize(10**9+7))
{2: 2, 3: 1, 5: 1}
{}

modありべき乗

これ掛け算そのままは多分あまり使うことはなくて、行列の掛け算とかもう少しコストの掛かる累乗計算で力を発揮すると思います。
あとこれ再帰だとちょっと遅いみたいなので、困るようならfor版書きますが、再帰のほうがプログラムが見やすいので、ひとまず再帰を使います。

def large_expo(x,n,mod):
    if n == 2:
        return (x*x)%mod
    elif n %2 == 1:
        return (large_expo(x,n-1,mod)*x)%mod
    else:
        temp = large_expo(x,n//2,mod)%mod
        return (temp*temp)%mod

modありnCk(組み合わせ)

フェルマーの小定理による逆元を利用。

nCkのnとmodで初期化します。複数回計算する必要がある場合はnを大きい方にあわせてとっておけば小さい方も計算できます。

便利なのでついでにこのクラスにpermutaionと逆元も実装しておきます。

class combination_mod:
    def __init__(self,n,mod):
        self.mod = mod
        self.fact = [1 for i in range(n)]
        for i in range(2,n+1):
            self.fact[i-1] = (self.fact[i-2]*i)%mod

    def expo(self,x,n):
        if n == 2:
            return (x * x) % self.mod
        elif n % 2 == 1:
            return (self.expo(x, n - 1) * x) % self.mod
        else:
            temp = self.expo(x, n // 2) % self.mod
            return (temp * temp) % self.mod
    def comb(self,n,k):
        a = (self.fact[n]*self.expo(self.fact[k],self.mod-2))%self.mod
        return (a*self.expo(self.fact[n-k],self.mod-2))%self.mod
    def invm(self,x):
        return (self.expo(self.fact[x],self.mod-2))%self.mod
    def perm(self,n,k):
        return (self.fact[n]*self.expo(self.fact[n-k],self.mod-2))%self.mod
cm = combination_mod(100,10**9+7)

print(cm.comb(4,2))
print(cm.comb(100,1))
print(cm.comb(100,50))
6
100
538992043
2
4
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
4