• 算法模板の数学&数论


    1、求逆元

    1 int inv(int a) {
    2     if(a == 1) return 1;
    3     return (MOD - MOD / a) * inv(MOD % a);
    4 }
    View Code

    2、线性筛法

     1 bool isPrime[MAXN];
     2 int label[MAXN], prime[MAXN];
     3 int n, total;
     4 
     5 void makePrime() {
     6     n = 100000;
     7     for(int i = 2; i <= n; ++i) {
     8         if(!label[i]) {
     9             prime[total++] = i;
    10             label[i] = total;
    11         }
    12         for(int j = 0; j < label[i]; ++j) {
    13             if(i * prime[j] > n) break;
    14             label[i * prime[j]] = j + 1;
    15         }
    16     }
    17     for(int i = 0; i < total; ++i) isPrime[prime[i]] = true;
    18 }
    View Code

    3、欧拉函数

    1 void phi_table(int n) {
    2     //for(int i = 2; i <= n; ++i) phi[i] = 0;
    3     phi[1] = 1;
    4     for(int i = 2; i <= n; ++i) if(!phi[i])
    5         for(int j = i; j <= n; j += i) {
    6             if(!phi[j]) phi[j] = j;
    7             phi[j] = phi[j] / i * (i - 1);
    8         }
    9 }
    View Code

    4、高精度类模板(减法除法的正确性未验证)

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <string>
      5 #include <algorithm>
      6 using namespace std;
      7 
      8 const int MAXN = 100010;
      9 
     10 struct bign {
     11     int len, s[MAXN];
     12 
     13     bign () {
     14         memset(s, 0, sizeof(s));
     15         len = 1;
     16     }
     17     bign (int num) { *this = num; }
     18     bign (const char *num) { *this = num; }
     19 
     20     void clear() {
     21         memset(s, 0, sizeof(s));
     22         len = 1;
     23     }
     24 
     25     bign operator = (const int num) {//数字
     26         char s[MAXN];
     27         sprintf(s, "%d", num);
     28         *this = s;
     29         return *this;
     30     }
     31     bign operator = (const char *num) {//字符串
     32         for(int i = 0; num[i] == '0'; num++) ;  //去前导0
     33         if(*num == 0) --num;
     34         len = strlen(num);
     35         for(int i = 0; i < len; ++i) s[i] = num[len-i-1] - '0';
     36         return *this;
     37     }
     38 
     39     bign operator + (const bign &b) const {
     40         bign c;
     41         c.len = 0;
     42         for(int i = 0, g = 0; g || i < max(len, b.len); ++i) {
     43             int x = g;
     44             if(i < len) x += s[i];
     45             if(i < b.len) x += b.s[i];
     46             c.s[c.len++] = x % 10;
     47             g = x / 10;
     48         }
     49         return c;
     50     }
     51 
     52     bign operator += (const bign &b) {
     53         *this = *this + b;
     54         return *this;
     55     }
     56 
     57     void clean() {
     58         while(len > 1 && !s[len-1]) len--;
     59     }
     60 
     61     bign operator * (const bign &b) {
     62         bign c;
     63         c.len = len + b.len;
     64         for(int i = 0; i < len; ++i) {
     65             for(int j = 0; j < b.len; ++j) {
     66                 c.s[i+j] += s[i] * b.s[j];
     67             }
     68         }
     69         for(int i = 0; i < c.len; ++i) {
     70             c.s[i+1] += c.s[i]/10;
     71             c.s[i] %= 10;
     72         }
     73         c.clean();
     74         return c;
     75     }
     76     bign operator *= (const bign &b) {
     77         *this = *this * b;
     78         return *this;
     79     }
     80 
     81     bign operator *= (const int &b) {//使用前要保证>len的位置都是空的
     82         for(int i = 0; i < len; ++i) s[i] *= b;
     83         for(int i = 0; i < len; ++i) {
     84             s[i + 1] += s[i] / 10;
     85             s[i] %= 10;
     86         }
     87         while(s[len]) {
     88             s[len + 1] += s[len] / 10;
     89             s[len] %= 10;
     90             ++len;
     91         }
     92         return *this;
     93     }
     94 
     95     bign operator - (const bign &b) {
     96         bign c;
     97         c.len = 0;
     98         for(int i = 0, g = 0; i < len; ++i) {
     99             int x = s[i] - g;
    100             if(i < b.len) x -= b.s[i];
    101             if(x >= 0) g = 0;
    102             else {
    103                 g = 1;
    104                 x += 10;
    105             }
    106             c.s[c.len++] = x;
    107         }
    108         c.clean();
    109         return c;
    110     }
    111     bign operator -= (const bign &b) {
    112         *this = *this - b;
    113         return *this;
    114     }
    115 
    116     bign operator / (const bign &b) {
    117         bign c, f = 0;
    118         for(int i = len - 1; i >= 0; i--) {
    119             f *= 10;
    120             f.s[0] = s[i];
    121             while(f >= b) {
    122                 f -= b;
    123                 c.s[i]++;
    124             }
    125         }
    126         c.len = len;
    127         c.clean();
    128         return c;
    129     }
    130     bign operator /= (const bign &b) {
    131         *this  = *this / b;
    132         return *this;
    133     }
    134 
    135     bign operator % (const bign &b) {
    136         bign r = *this / b;
    137         r = *this - r*b;
    138         return r;
    139     }
    140     bign operator %= (const bign &b) {
    141         *this = *this % b;
    142         return *this;
    143     }
    144 
    145     bool operator < (const bign &b) {
    146         if(len != b.len) return len < b.len;
    147         for(int i = len-1; i >= 0; i--) {
    148             if(s[i] != b.s[i]) return s[i] < b.s[i];
    149         }
    150         return false;
    151     }
    152 
    153     bool operator > (const bign &b) {
    154         if(len != b.len) return len > b.len;
    155         for(int i = len-1; i >= 0; i--) {
    156             if(s[i] != b.s[i]) return s[i] > b.s[i];
    157         }
    158         return false;
    159     }
    160 
    161     bool operator == (const bign &b) {
    162         return !(*this > b) && !(*this < b);
    163     }
    164 
    165     bool operator != (const bign &b) {
    166         return !(*this == b);
    167     }
    168 
    169     bool operator <= (const bign &b) {
    170         return *this < b || *this == b;
    171     }
    172 
    173     bool operator >= (const bign &b) {
    174         return *this > b || *this == b;
    175     }
    176 
    177     string str() const {
    178         string res = "";
    179         for(int i = 0; i < len; ++i) res = char(s[i]+'0') + res;
    180         return res;
    181     }
    182 };
    183 
    184 istream& operator >> (istream &in, bign &x) {
    185     string s;
    186     in >> s;
    187     x = s.c_str();
    188     return in;
    189 }
    190 
    191 ostream& operator << (ostream &out, const bign &x) {
    192     out << x.str();
    193     return out;
    194 }
    View Code

    5、单纯形(UVA 10498)//只能解标准形式

     1 #include <cstdio>
     2 #include <iostream>
     3 #include <algorithm>
     4 #include <cstring>
     5 #include <cmath>
     6 using namespace std;
     7 
     8 const double EPS = 1e-10;
     9 const int MAXN = 55;
    10 const int INF = 0x3fff3fff;
    11 
    12 inline int sgn(double x) {
    13     return (x > EPS) - (x < -EPS);
    14 }
    15 
    16 double A[MAXN][MAXN];
    17 double b[MAXN], c[MAXN];
    18 int N[MAXN], B[MAXN];
    19 int n, m;
    20 double v;
    21 
    22 bool init() {
    23     N[0] = B[0] = v = 0;
    24     for(int i = 1; i <= n; ++i) N[++N[0]] = i;
    25     for(int i = 1; i <= m; ++i) B[++B[0]] = n + i;
    26     return true;
    27 }
    28 
    29 void pivot(int l, int e) {
    30     b[e] = b[l] / A[l][e];
    31     A[e][l] = 1.0 / A[l][e];
    32     for(int i = 1; i <= N[0]; ++i) {
    33         int &x = N[i];
    34         if(x != e) A[e][x] = A[l][x] / A[l][e];
    35     }
    36     for(int i = 1; i <= B[0]; ++i) {
    37         int &y = B[i];
    38         b[y] -= A[y][e] * b[e];
    39         A[y][l] = -A[y][e] * A[e][l];
    40         for(int j = 1; j <= N[0]; ++j) {
    41             int &x = N[j];
    42             if(x != e) A[y][x] -= A[e][x] * A[y][e];
    43         }
    44     }
    45     v += b[e] * c[e];
    46     c[l] = -A[e][l] * c[e];
    47     for(int i = 1; i <= N[0]; ++i) {
    48         int &x = N[i];
    49         if(x != e) c[x] -= A[e][x] * c[e];
    50     }
    51     for(int i = 1; i <= N[0]; ++i) if(N[i] == e) N[i] = l;
    52     for(int i = 1; i <= B[0]; ++i) if(B[i] == l) B[i] = e;
    53 }
    54 
    55 bool simplex() {
    56     while(true) {
    57         int e = MAXN;
    58         for(int i = 1; i <= N[0]; ++i) {
    59             int &x = N[i];
    60             if(sgn(c[x]) > 0 && x < e) e = x;
    61         }
    62         if(e == MAXN) break;
    63         double delta = -1;
    64         int l = MAXN;
    65         for(int i = 1; i <= B[0]; ++i) {
    66             int &y = B[i];
    67             if(sgn(A[y][e]) > 0) {
    68                 double tmp = b[y] / A[y][e];
    69                 if(delta == -1 || sgn(tmp - delta) < 0 || (sgn(tmp - delta) == 0 && y < l)) {
    70                     delta = tmp;
    71                     l = y;
    72                 }
    73             }
    74         }
    75         if(l == MAXN) return false;
    76         pivot(l, e);
    77     }
    78     return true;
    79 }
    80 
    81 int main() {
    82     while(scanf("%d%d", &n, &m) != EOF) {
    83         for(int i = 1; i <= n; ++i) scanf("%lf", &c[i]);
    84         for(int i = 1; i <= m; ++i) {
    85             for(int j = 1; j <= n; ++j) scanf("%lf", &A[n + i][j]);
    86             scanf("%lf", &b[n + i]);
    87         }
    88         init();
    89         simplex();
    90         printf("Nasa can spend %d taka.
    ", (int)ceil(v * m));
    91     }
    92 }
    View Code

    6、高斯消元(-1无解,0无穷解,1唯一解)

     1 int guess_eliminatioin() {
     2     int rank = 0;
     3     for(int i = 0, t = 0; i < m && t < n; ++i, ++t) {
     4         int r = i;
     5         for(int j = i + 1; j < m; ++j)
     6             if(mat[r][t].val < mat[j][t].val) r = j;
     7         if(mat[r][t].isZero()) { --i; continue;}
     8         else ++rank;
     9         if(r != i) for(int j = 0; j <= n; ++j) swap(mat[i][j], mat[r][j]);
    10         for(int j = n; j >= t; --j)
    11             for(int k = i + 1; k < m; ++k) mat[k][j] -= mat[i][j] * mat[k][t] / mat[i][t];
    12     }
    13     for(int i = rank; i < m; ++i)
    14         if(!mat[i][n].isZero()) return -1;
    15     if(rank < n) return 0;
    16     for(int i = n - 1; i >= 0; --i) {
    17         for(int j = i + 1; j < n; ++j)
    18             mat[i][n] -= mat[j][n] * mat[i][j];
    19         mat[i][n] = mat[i][n] / mat[i][i];
    20     }
    21     return 1;
    22 }
    View Code

    7、离散对数(小步大步算法)(POJ 3243)

     1 #include <cstdio>
     2 #include <iostream>
     3 #include <algorithm>
     4 #include <cstring>
     5 #include <cmath>
     6 using namespace std;
     7 typedef long long LL;
     8 
     9 const int SIZEH = 65537;
    10 
    11 struct hash_map {
    12     int head[SIZEH], size;
    13     int next[SIZEH];
    14     LL state[SIZEH], val[SIZEH];
    15 
    16     void init() {
    17         memset(head, -1, sizeof(head));
    18         size = 0;
    19     }
    20 
    21     void insert(LL st, LL sv) {
    22         LL h = st % SIZEH;
    23         for(int p = head[h]; ~p; p = next[p])
    24             if(state[p] == st) return ;
    25         state[size] = st; val[size] = sv;
    26         next[size] = head[h]; head[h] = size++;
    27     }
    28 
    29     LL find(LL st) {
    30         LL h = st % SIZEH;
    31         for(int p = head[h]; ~p; p = next[p])
    32             if(state[p] == st) return val[p];
    33         return -1;
    34     }
    35 } hashmap;
    36 
    37 void exgcd(LL a, LL b, LL &x, LL &y) {
    38     if(!b) x = 1, y = 0;
    39     else {
    40         exgcd(b, a % b, y, x);
    41         y -= x * (a / b);
    42     }
    43 }
    44 
    45 LL inv(LL a, LL n) {
    46     LL x, y;
    47     exgcd(a, n, x, y);
    48     return (x + n) % n;
    49 }
    50 
    51 LL pow_mod(LL x, LL p, LL n) {
    52     LL ret = 1;
    53     while(p) {
    54         if(p & 1) ret = (ret * x) % n;
    55         x = (x * x) % n;
    56         p >>= 1;
    57     }
    58     return ret;
    59 }
    60 
    61 LL BabyStep_GiantStep(LL a, LL b, LL n) {
    62     for(LL i = 0, e = 1; i <= 64; ++i) {
    63         if(e == b) return i;
    64         e = (e * a) % n;
    65     }
    66     LL k = 1, cnt = 0;
    67     while(true) {
    68         LL t = __gcd(a, n);
    69         if(t == 1) break;
    70         if(b % t != 0) return -1;
    71         n /= t; b /= t; k = (k * a / t) % n;
    72         ++cnt;
    73     }
    74     hashmap.init();
    75     hashmap.insert(1, 0);
    76     LL e = 1, m = LL(ceil(sqrt(n + 0.5)));
    77     for(int i = 1; i < m; ++i) {
    78         e = (e * a) % n;
    79         hashmap.insert(e, i);
    80     }
    81     LL p = inv(pow_mod(a, m, n), n), v = inv(k, n);
    82     for(int i = 0; i < m; ++i) {
    83         LL t = hashmap.find((b * v) % n);
    84         if(t != -1) return i * m + t + cnt;
    85         v = (v * p) % n;
    86     }
    87     return -1;
    88 }
    89 
    90 int main() {
    91     LL x, z, k;
    92     while(cin>>x>>z>>k) {
    93         if(x == 0 && z == 0 && k == 0) break;
    94         LL ans = BabyStep_GiantStep(x % z, k % z, z);
    95         if(ans == -1) puts("No Solution");
    96         else cout<<ans<<endl;
    97     }
    98 }
    View Code

    8、母函数

     1 /*
     2 G(x) = 1 + x + x^2 + x^3 + …… = 1 / (1 - x)
     3 G(x) = 1 + 2x + 3x^2 + 4x^3 + …… = 1 / (1 - x)^2
     4 
     5 指数型母函数
     6 G(x) = 1 + x + x^2 / 2! + x^3 / 3! + x^4 / 4! + …… = e^x
     7 <1, -1, 1, -1, 1, -1, ……> = e^(-x)
     8 <0, 1, 0, 1, 0, 1, ……> = (e^x - e^(-x)) / 2
     9 <1, 0, 1, 0, 1, 0, ……> = (e^x + e^(-x)) / 2
    10 */
    View Code

    9、插头DP(URAL1519 括号表示法)

      1 #include <iostream>
      2 #include <algorithm>
      3 #include <cstring>
      4 #include <cstdio>
      5 using namespace std;
      6 typedef long long LL;
      7 
      8 const int MAXH = 20010;
      9 const int SIZEH = 13131;
     10 
     11 struct hash_map {
     12     int head[SIZEH];
     13     int next[MAXH], state[MAXH];
     14     LL value[MAXH];
     15     int size;
     16 
     17     void init() {
     18         memset(head, -1, sizeof(head));
     19         size = 0;
     20     }
     21 
     22     void insert(int st, LL tv) {
     23         int h = st % SIZEH;
     24         for(int i = head[h]; ~i; i = next[i]) {
     25             if(state[i] == st) {
     26                 value[i] += tv;
     27                 return ;
     28             }
     29         }
     30         value[size] = tv; state[size] = st;
     31         next[size] = head[h]; head[h] = size++;
     32     }
     33 } hashmap[2];
     34 
     35 hash_map *cur, *last;
     36 int acc[] = {0, -1, 1, 0};
     37 
     38 int n, m, en, em;
     39 char mat[14][14];
     40 
     41 int getB(int state, int i) {
     42     i <<= 1;
     43     return (state >> i) & 3;
     44 }
     45 
     46 int getLB(int state, int i) {
     47     int ret = i, cnt = 1;
     48     while(cnt) cnt += acc[getB(state, --ret)];
     49     return ret;
     50 }
     51 
     52 int getRB(int state, int i) {
     53     int ret = i, cnt = -1;
     54     while(cnt) cnt += acc[getB(state, ++ret)];
     55     return ret;
     56 }
     57 
     58 void setB(int &state, int i, int tv) {
     59     i <<= 1;
     60     state = (state & ~(3 << i)) | (tv << i);
     61 }
     62 
     63 void update(int x, int y, int state, LL tv) {
     64     int left = getB(state, y);
     65     int up = getB(state, y + 1);
     66     if(mat[x][y] == '*') {
     67         if(left == 0 && up == 0) cur->insert(state, tv);
     68         return ;
     69     }
     70     if(left == 0 && up == 0) {
     71         if(x == n - 1 || y == m - 1) return ;
     72         int newState = state;
     73         setB(newState, y, 1);
     74         setB(newState, y + 1, 2);
     75         cur->insert(newState, tv);
     76     } else if(left == 0 || up == 0) {
     77         if(x < n - 1) {
     78             int newState = state;
     79             setB(newState, y, up + left);
     80             setB(newState, y + 1, 0);
     81             cur->insert(newState, tv);
     82         }
     83         if(y < m - 1) {
     84             int newState = state;
     85             setB(newState, y, 0);
     86             setB(newState, y + 1, up + left);
     87             cur->insert(newState, tv);
     88         }
     89     } else {
     90         int newState = state;
     91         setB(newState, y, 0);
     92         setB(newState, y + 1, 0);
     93         if(left == 1 && up == 1) setB(newState, getRB(state, y + 1), 1);
     94         if(left == 1 && up == 2 && !(x == en && y == em)) return ;
     95         if(left == 2 && up == 2) setB(newState, getLB(state, y), 2);
     96         cur->insert(newState, tv);
     97     }
     98 }
     99 
    100 void findend() {
    101     for(en = n - 1; en >= 0; --en)
    102         for(em = m - 1; em >= 0; --em) if(mat[en][em] == '.') return ;
    103 }
    104 
    105 LL solve() {
    106     findend();
    107     cur = hashmap, last = hashmap + 1;
    108     last->init();
    109     last->insert(0, 1);
    110     for(int i = 0; i < n; ++i) {
    111         int sz = last->size;
    112         for(int k = 0; k < sz; ++k) last->state[k] <<= 2;
    113         for(int j = 0; j < m; ++j) {
    114             cur->init();
    115             sz = last->size;
    116             for(int k = 0; k < sz; ++k)
    117                 update(i, j, last->state[k], last->value[k]);
    118             swap(cur, last);
    119         }
    120     }
    121     return last->size ? last->value[0] : 0;
    122 }
    123 
    124 int main() {
    125     scanf("%d%d", &n, &m);
    126     for(int i = 0; i < n; ++i) scanf("%s", mat[i]);
    127     cout<<solve()<<endl;
    128 }
    View Code

    10、快速傅里叶变换(HDU1402)

     1 #include <cmath>
     2 #include <algorithm>
     3 #include <cstdio>
     4 #include <iostream>
     5 #include <cstring>
     6 #include <complex>
     7 using namespace std;
     8 typedef complex<double> Complex;
     9 const double PI = acos(-1);
    10 
    11 void fft_prepare(int maxn, Complex *&e) {
    12     e = new Complex[2 * maxn - 1];
    13     e += maxn - 1;
    14     e[0] = 1;
    15     for (int i = 1; i < maxn; i <<= 1)
    16         e[i] = Complex(cos(2 * PI * i / maxn), sin(2 * PI * i / maxn));
    17     for (int i = 3; i < maxn; i++)
    18         if ((i & -i) != i) e[i] = e[i - (i & -i)] * e[i & -i];
    19     for (int i = 1; i < maxn; i++) e[-i] = e[maxn - i];
    20 }
    21 /* f = 1: dft; f = -1: idft */
    22 void dft(Complex *a, int N, int f, Complex *e, int maxn) {
    23     int d = maxn / N * f;
    24     Complex x;
    25     for (int n = N, m; m = n / 2, m >= 1; n = m, d *= 2)
    26         for (int i = 0; i < m; i++)
    27             for (int j = i; j < N; j += n)
    28                 x = a[j] - a[j + m], a[j] += a[j + m], a[j + m] = x * e[d * i];
    29     for (int i = 0, j = 1; j < N - 1; j++) {
    30         for (int k = N / 2; k > (i ^= k); k /= 2);
    31         if (j < i) swap(a[i], a[j]);
    32     }
    33 }
    34 
    35 const int MAXN = 131072;
    36 Complex x1[MAXN], x2[MAXN];
    37 char s1[MAXN / 2], s2[MAXN / 2];
    38 int sum[MAXN];
    39 
    40 int main() {
    41     Complex* e = 0;
    42     fft_prepare(MAXN, e);
    43     while(scanf("%s%s",s1,s2) != EOF) {
    44         int n1 = strlen(s1);
    45         int n2 = strlen(s2);
    46         int n = 1;
    47         while(n < n1 * 2 || n < n2 * 2) n <<= 1;
    48         for(int i = 0; i < n; ++i) {
    49             x1[i] = i < n1 ? s1[n1 - 1 - i] - '0' : 0;
    50             x2[i] = i < n2 ? s2[n2 - 1 - i] - '0' : 0;
    51         }
    52 
    53         dft(x1, n, 1, e, MAXN);
    54         dft(x2, n, 1, e, MAXN);
    55         for(int i = 0; i < n; ++i) x1[i] = x1[i] * x2[i];
    56         dft(x1, n, -1, e, MAXN);
    57         for(int i = 0; i < n; ++i) x1[i] /= n;
    58 
    59         for(int i = 0; i < n; ++i) sum[i] = round(x1[i].real());
    60         for(int i = 0; i < n; ++i) {
    61             sum[i + 1] += sum[i] / 10;
    62             sum[i] %= 10;
    63         }
    64 
    65         n = n1 + n2 - 1;
    66         while(sum[n] <= 0 && n > 0) --n;
    67         for(int i = n; i >= 0;i--) printf("%d", sum[i]);
    68         puts("");
    69     }
    70 }
    View Code

    11、求解线性同余方程组(POJ 2891 exgcd)

     1 void exgcd(LL a, LL b, LL &d, LL &x, LL &y) {
     2     if(!b) d = a, x = 1, y = 0;
     3     else {
     4         exgcd(b, a % b, d, y, x);
     5         y -= x * (a / b);
     6     }
     7 }
     8 
     9 int main() {
    10     LL k, a1, a2, r1, r2;
    11     while(scanf("%I64d", &k) != EOF) {
    12         bool flag = true;
    13         scanf("%I64d%I64d", &a1, &r1);
    14         for(int i = 1; i < k; ++i) {
    15             scanf("%I64d%I64d", &a2, &r2);
    16             if(!flag) continue;
    17             LL r = r2 - r1, d, k1, k2;
    18             exgcd(a1, a2, d, k1, k2);
    19             if(r % d) flag = false;
    20             LL t = a2 / d;
    21             k1 = (r / d * k1 % t + t) % t;
    22             r1 = r1 + a1 * k1;
    23             a1 = a1 / d * a2;
    24         }
    25         printf("%I64d
    ", flag ? r1 : -1);
    26     }
    27 }
    View Code
  • 相关阅读:
    Servlet梳理一
    String和StringBuffer的区别
    谈谈面对将要来到的第一份工作
    shell grep文本搜索
    Shell cut分割
    python的学习之路:计算
    web端和手机端测试有什么不同
    让TortoiseGit记住帐号密码方法
    操纵IE,模拟用户登录
    MVC路由配置.html不能识别
  • 原文地址:https://www.cnblogs.com/oyking/p/3269151.html
Copyright © 2020-2023  润新知