14
7

More than 3 years have passed since last update.

競技プログラミングでよく使う便利系関数をまとめてみた

Last updated at Posted at 2019-12-23

競技プログラミングでよく使う便利系関数をまとめてみた

 今回はAtCoderでよく使う便利系関数をまとめてみました。とりあいず今思いつく範囲で書いてますが、思い出したら追加していきます。

0.前提

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MOD=pow(10,9)+7;

 前提として以上のようにしています。

1.最大公約数、最小公倍数

ll gcd(ll a,ll b){
    if(a<b)swap(a,b);
    if(a%b==0)return b;
    return gcd(a%b,b);
}
ll lcm(ll a,ll b){
    return a/gcd(a,b)*b;
}

 gcdが最大公約数、lcmが最小公倍数です。どちらも計算量はO(log N)程度らしいです。lcmはa/gcd(a,b)*bとしてるのがポイントです。(オーバーフローしないように)

2.modPow

ll modPow(ll x,ll n,ll mod=MOD){
    if(n==0)return 1;
    if(n%2==0)return modPow(x*x,n/2,mod)%mod;
    return x%mod*modPow(x,n-1,mod)%mod;
}

 xのn乗をmodで割ったものを返します。繰り返し2乗法を用いてるため計算量はO(log N)と高速です。

3.各位の和を返す

ll getSumDigit(ll N){
    string s=to_string(N);
    ll ret=0;
    for(int i=0;i<s.size();i++)ret+=(s[i]-'0');
    return ret;
}

4.nCk mod p

class Combination{
public:
    vector<ll>fac;
    vector<ll>finv;
    vector<ll>inv;

    Combination(ll MAX,ll mod=MOD){
        fac.resize(MAX+2);
        finv.resize(MAX+2);
        inv.resize(MAX+2);
        fac[0] = fac[1] = 1;
        finv[0] = finv[1] = 1;
        inv[1] = 1;
        for (int i = 2; i < MAX; i++){
            fac[i] = fac[i - 1] * i % MOD;
            inv[i] = MOD - inv[MOD%i] * (MOD / i) % MOD;
            finv[i] = finv[i - 1] * inv[i] % MOD;
        }
    }

    ll com(int n, int k){
        if (n < k) return 0;
        if (n < 0 || k < 0) return 0;
        return fac[n] * (finv[k] * finv[n - k] % MOD) % MOD;
    }
};

コンビネーションをmodで割った余剰を求めるものを求めるものです。この記事を参考(丸パクリ)してます。本家ではグローバル変数でやってましたが、クラス化してます。前処理でO(N)、comはO(1)で返すことができます。

5.ランレングス圧縮っぽいもの

vector<ll> countVector(vector<ll>v,ll guard=-1){
    ll size=v.size();
    //番兵を追加(初期値は-1)
    v.push_back(guard);
    vector<ll>ret;
    ll count=1;
    for(int i=0;i<size;i++){
        if(v[i]==v[i+1]){
            count++;
        }else{
            ret.push_back(count);
            count=1;
        }
    }
    return ret;
}

(2019/12/24追記)うまく言えませんが、例えば{2,2,2,3,3,1,2}を渡したら{3,2,1,1}みたいに連続する個数の配列を返す関数です。意外とよく使うので便利です。
(2019/12/29追記)ランレングス圧縮なんていうそうです。

INF.最後に

 一旦はこんな感じでまとめてみました。思い出したら追加していきます。お役になてれば幸いです。最後になりましたが、コードを勝手に参考にさせていただいた方ありがとうございましたm(_ _)m

14
7
0

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
14
7