1. 程式人生 > >acm比賽常用模板

acm比賽常用模板

亂七八糟模板

  • 標頭檔案,巨集定義,讀入掛
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <string>
#include <bitset>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <algorithm> #include <sstream> #include <stack> #include <iomanip> #define ll long long #define ull unsigned long long #define PI acos(-1.0) #define eps 1e-12 #define fi first #define se second #define MEM(a,b) memset((a),(b),sizeof(a)) #define mod(x) ((x)%MOD) #define pii pair<int,int>
#define wz cout<<"-----"<<endl; const int INF_INT = 2147483647; const ll INF_LL = 9223372036854775807LL; const ull INF_ULL = 18446744073709551615Ull; const ll P = 92540646808111039LL; const ll maxn = 1e5 + 10, MOD = 1e9 + 7; const int Move[4][2] = {-1,0,1,0,0,1,0,-1}; const int Move_[8][2] = {-1,-1
,-1,0,-1,1,0,-1,0,1,1,-1,1,0,1,1}; inline int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 結構體過載運算子
//與平時cmp函式 相反
bool operator < (const node &p) const {
        return r > p.r;
    }
  
  • 1
  • 2
  • 3
  • 4

資料結構

  • 樹狀陣列

/*
單點更新,區間查詢,(也可區間更新加),逆序對等等
*/
int lowerbit(int x) {
    return x & -x;
}

void add(int p, int x) {
    while (p < maxn) {
        d[p] += x;
        p += lowerbit(p);
    }
}
int sum(int p) {
    int res = 0;
    while (p) {
        res += d[p];
        p -= lowerbit(p);
    }
    return res;
}

  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

數論模板

  • 快速冪
ll quick_pow(ll a,ll b) {
    ll res = 1;
    while (b) {
        if (b & 1) {
            res = a * res;
        }
        a = a * a;
        b >>= 1;
    }
    return res;
}
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 矩陣快速冪
#include<bits/stdc++.h>
#define ll long long
#define mod(x) ((x)%MOD)

using namespace std;

const ll MOD = 1e9 + 7;

struct mat{
    ll m[3][3];
}a,ans,unit;

void init() {
    memset(unit.m,0,sizeof(unit.m));
    memset(a.m,0,sizeof(a.m));
    unit.m[0][0] = 1;
    unit.m[1][1] = 1;
    a.m[0][0] = 3;
    a.m[0][1] = 1;
    a.m[1][0] = 1;
    a.m[1][1] = 3;
}

mat operator * (mat m1,mat m2) {
    mat t;
    ll r;
    for(int i = 0;i < 3;i++) {
        for(int j = 0;j < 3;j++) {
            r = 0;
            for(int k = 0;k < 3;k++) {
                r = mod(r*1ll + mod(mod(m1.m[i][k])*1ll*mod(m2.m[k][j])));
            }
            t.m[i][j] = r;
        }
    }
    return t;
}

mat quick_pow(ll x) {
    mat t = unit;
    while(x) {
        if(x & 1) {
            t = t*a;
        }
        a = a*a;
        x >>= 1;
    }
    return t;
}
int main(){
    init();
    ans = quick_pow(n);
}
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 素數的兩種篩法
bool isp[maxn];
int p[maxn], len;

bool isp[100];
void init() {
    int m = (int)sqrt(maxn+0.5);
    for(int i = 2;i <= m;i++) {
        if(!isp[i]) {
            for(int j = i*i;j <= maxn;j += i) {
                isp[j] = true;
            }
        }
    }
}

void init() { //推薦這個,較快
    isp[0] = isp[1] = true;
    for (int i = 2; i < maxn; i++) {
        if(!isp[i]) p[++len] = i;
        for (int j = 1; j <= len && p[j]*i < maxn; j++) {
            isp[i*p[j]] = true;
            if (i%p[j] == 0) break;
        }
    }
}
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 尤拉函式 
    在數論,對正整數n,尤拉函式是小於n的正整數中與n互質的數的數目(φ(1)=1)。
int euler_phi(int n){ //單個值
    int m = (int)sqrt(n + 0.5);
    int ans = n;
    for (int i = 2;i <= m;i++){
        if (n%i == 0){       //如果存在素因子
            ans = ans/i*(i-1); 
            while (n%i == 0) n/=i;
        }
    }
    if(n > 1) ans = ans/n*(n-1); //考慮n本身
    return ans;
}

void phi_table(int n,int *phi){ //尤拉表
    for (int i = 1;i <= n;i++) phi[i] = i;
    for(int i = 2;i <= n;i++){
        if(phi[i] == i){   //類似於Eratosthenes篩法這裡
            for(int j = i;j <= n;j+=i){
                phi[j] = phi[j]/i*(i-1);
            }
        }
    }       
}
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 歐幾里得GCD,擴充套件~ 
    歐幾里德演算法又稱輾轉相除法,用於計算兩個整數a,b的最大公約數(greatest common divisor)。 
    擴充套件歐幾里德演算法是用來在已知a, b求解一組x,y,使它們滿足貝祖等式: ax+by = gcd(a, b) =d(解一定存在,根據數論中的相關定理)。擴充套件歐幾里德常用在求解模線性方程及方程組中。
ll gcd(ll a,ll b) {
    return b == 0 ? a : gcd(b, a % b);
}

void exgcd(ll a, ll b, ll &d, ll &x, ll &y) {
    if(!b) d=a,x=1,y=0;
    else exgcd(b, a % b, d, y, x),y -= x * (a / b);
}
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 逆元 
    方程ax≡1(mod p),的解稱為a關於模p的逆,當gcd(a,p)==1(即a,p互質)時,方程有唯一解,否則無解。 
    對於一些題目會要求把結果MOD一個數,通常是一個較大的質數,對於加減乘法通過同餘定理可以直接拆開計算,但對於(a/b)%MOD這個式子,是不可以寫成(a%MOD/b%MOD)%MOD的,但是可以寫為(a*b^-1)%MOD,其中b^-1表示b的逆元。
ll getinv (ll a,ll p) {
    ll d, x, y;
    exgcd (a, p, d, x, y);
    return (x + p) % p == 0 ? p : (x + p) % p;
}
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 中國剩餘定理(CRT) ,擴充套件~

中國剩餘定理給出了以下的一元線性同餘方程組:

這裡寫圖片描述 
假設整數m1,m2, ... ,mn兩兩互質,則對任意的整數:a1,a2, ... ,an,方程組 有解,即x,擴充套件剩餘定理就是m1,m2···mn,這幾個數不兩兩互質的情況

ll CRT(ll M){
    ll sum=0,tmp,v;
    for (int i=1;i<=cnt;i++){
        tmp=M/m[i];
        v=getInv(tmp,m[i]);
        sum=(sum+tmp*a[i]*v)%M;
    }
    return sum;
}

/*以下是ECRT*/

bool merge(ll &a1,ll &m1,ll a2,ll m2){
    ll c,d,x,a3,m3;
    c=a2-a1;d=__gcd(m1,m2);
    if (c%d!=0) return false;
    c=c/d;m1=m1/d;m2=m2/d;
    x=getinv(m1,m2);
    x=(x*c)%m2;
    x=x*(m1*d)+a1;
    m3=m1*m2*d;
    a3=(x%m3+m3)%m3;
    a1=a3;m1=m3;
    return true;
}
ll ECRT(){
    ll A=a[1],M=r[1];
    for (int i=2;i<=n;i++) //無解返回 -1
      if (!merge(A,M,a[i],r[i]))
        return -1;
    return (A%M+M)%M;
}
  
  • 1