简单的模板整理(待续)

来源:互联网 发布:广数g92车英制螺纹编程 编辑:程序博客网 时间:2024/06/15 10:01

ACM模板 0.4

鉴于被穿了小鞋,马而克之。 __φ(..;)

你们要的萝莉


1.高精度

1) C++版

#include<iostream> #include<string> #include<iomanip> #include<algorithm> using namespace std; #define MAXN 9999#define MAXSIZE 10#define DLEN 4class BigNum{ private:     int a[500];    //可以控制大数的位数     int len;       //大数长度public:     BigNum(){ len = 1;memset(a,0,sizeof(a)); }   //构造函数    BigNum(const int);       //将一个int类型的变量转化为大数    BigNum(const char*);     //将一个字符串类型的变量转化为大数    BigNum(const BigNum &);  //拷贝构造函数    BigNum &operator=(const BigNum &);   //重载赋值运算符,大数之间进行赋值运算    friend istream& operator>>(istream&,  BigNum&);   //重载输入运算符    friend ostream& operator<<(ostream&,  BigNum&);   //重载输出运算符    BigNum operator+(const BigNum &) const;   //重载加法运算符,两个大数之间的相加运算     BigNum operator-(const BigNum &) const;   //重载减法运算符,两个大数之间的相减运算     BigNum operator*(const BigNum &) const;   //重载乘法运算符,两个大数之间的相乘运算     BigNum operator/(const int   &) const;    //重载除法运算符,大数对一个整数进行相除运算    BigNum operator^(const int  &) const;    //大数的n次方运算    int    operator%(const int  &) const;    //大数对一个int类型的变量进行取模运算        bool   operator>(const BigNum & T)const;   //大数和另一个大数的大小比较    bool   operator>(const int & t)const;      //大数和一个int类型的变量的大小比较    void print();       //输出大数}; BigNum::BigNum(const int b)     //将一个int类型的变量转化为大数{     int c,d = b;    len = 0;    memset(a,0,sizeof(a));    while(d > MAXN)    {        c = d - (d / (MAXN + 1)) * (MAXN + 1);         d = d / (MAXN + 1);        a[len++] = c;    }    a[len++] = d;}BigNum::BigNum(const char*s)     //将一个字符串类型的变量转化为大数{    int t,k,index,l,i;    memset(a,0,sizeof(a));    l=strlen(s);       len=l/DLEN;    if(l%DLEN)        len++;    index=0;    for(i=l-1;i>=0;i-=DLEN)    {        t=0;        k=i-DLEN+1;        if(k<0)            k=0;        for(int j=k;j<=i;j++)            t=t*10+s[j]-'0';        a[index++]=t;    }}BigNum::BigNum(const BigNum & T) : len(T.len)  //拷贝构造函数{     int i;     memset(a,0,sizeof(a));     for(i = 0 ; i < len ; i++)        a[i] = T.a[i]; } BigNum & BigNum::operator=(const BigNum & n)   //重载赋值运算符,大数之间进行赋值运算{    int i;    len = n.len;    memset(a,0,sizeof(a));     for(i = 0 ; i < len ; i++)         a[i] = n.a[i];     return *this; }istream& operator>>(istream & in,  BigNum & b)   //重载输入运算符{    char ch[MAXSIZE*4];    int i = -1;    in>>ch;    int l=strlen(ch);    int count=0,sum=0;    for(i=l-1;i>=0;)    {        sum = 0;        int t=1;        for(int j=0;j<4&&i>=0;j++,i--,t*=10)        {            sum+=(ch[i]-'0')*t;        }        b.a[count]=sum;        count++;    }    b.len =count++;    return in;}ostream& operator<<(ostream& out,  BigNum& b)   //重载输出运算符{    int i;      cout << b.a[b.len - 1];     for(i = b.len - 2 ; i >= 0 ; i--)    {         cout.width(DLEN);         cout.fill('0');         cout << b.a[i];     }     return out;}BigNum BigNum::operator+(const BigNum & T) const   //两个大数之间的相加运算{    BigNum t(*this);    int i,big;      //位数       big = T.len > len ? T.len : len;     for(i = 0 ; i < big ; i++)     {         t.a[i] +=T.a[i];         if(t.a[i] > MAXN)         {             t.a[i + 1]++;             t.a[i] -=MAXN+1;         }     }     if(t.a[big] != 0)        t.len = big + 1;     else        t.len = big;       return t;}BigNum BigNum::operator-(const BigNum & T) const   //两个大数之间的相减运算 {      int i,j,big;    bool flag;    BigNum t1,t2;    if(*this>T)    {        t1=*this;        t2=T;        flag=0;    }    else    {        t1=T;        t2=*this;        flag=1;    }    big=t1.len;    for(i = 0 ; i < big ; i++)    {        if(t1.a[i] < t2.a[i])        {             j = i + 1;             while(t1.a[j] == 0)                j++;             t1.a[j--]--;             while(j > i)                t1.a[j--] += MAXN;            t1.a[i] += MAXN + 1 - t2.a[i];         }         else            t1.a[i] -= t2.a[i];    }    t1.len = big;    while(t1.a[len - 1] == 0 && t1.len > 1)    {        t1.len--;         big--;    }    if(flag)        t1.a[big-1]=0-t1.a[big-1];    return t1; } BigNum BigNum::operator*(const BigNum & T) const   //两个大数之间的相乘运算 {     BigNum ret;     int i,j,up;     int temp,temp1;       for(i = 0 ; i < len ; i++)    {         up = 0;         for(j = 0 ; j < T.len ; j++)        {             temp = a[i] * T.a[j] + ret.a[i + j] + up;             if(temp > MAXN)            {                 temp1 = temp - temp / (MAXN + 1) * (MAXN + 1);                 up = temp / (MAXN + 1);                 ret.a[i + j] = temp1;             }             else            {                 up = 0;                 ret.a[i + j] = temp;             }         }         if(up != 0)             ret.a[i + j] = up;     }     ret.len = i + j;     while(ret.a[ret.len - 1] == 0 && ret.len > 1)        ret.len--;     return ret; } BigNum BigNum::operator/(const int & b) const   //大数对一个整数进行相除运算{     BigNum ret;     int i,down = 0;       for(i = len - 1 ; i >= 0 ; i--)    {         ret.a[i] = (a[i] + down * (MAXN + 1)) / b;         down = a[i] + down * (MAXN + 1) - ret.a[i] * b;     }     ret.len = len;     while(ret.a[ret.len - 1] == 0 && ret.len > 1)        ret.len--;     return ret; }int BigNum::operator %(const int & b) const    //大数对一个int类型的变量进行取模运算    {    int i,d=0;    for (i = len-1; i>=0; i--)    {        d = ((d * (MAXN+1))% b + a[i])% b;      }    return d;}BigNum BigNum::operator^(const int & n) const    //大数的n次方运算{    BigNum t,ret(1);    int i;    if(n<0)        exit(-1);    if(n==0)        return 1;    if(n==1)        return *this;    int m=n;    while(m>1)    {        t=*this;        for( i=1;i<<1<=m;i<<=1)        {            t=t*t;        }        m-=i;        ret=ret*t;        if(m==1)            ret=ret*(*this);    }    return ret;}bool BigNum::operator>(const BigNum & T) const   //大数和另一个大数的大小比较{     int ln;     if(len > T.len)        return true;     else if(len == T.len)    {         ln = len - 1;         while(a[ln] == T.a[ln] && ln >= 0)            ln--;         if(ln >= 0 && a[ln] > T.a[ln])            return true;         else            return false;     }     else        return false; }bool BigNum::operator >(const int & t) const    //大数和一个int类型的变量的大小比较{    BigNum b(t);    return *this>b;}void BigNum::print()    //输出大数{     int i;       cout << a[len - 1];     for(i = len - 2 ; i >= 0 ; i--)    {         cout.width(DLEN);         cout.fill('0');         cout << a[i];     }     cout << endl;}int main(){    int i,n;    BigNum x[101];      //定义大数的对象数组    x[0]=1;    for(i=1;i<101;i++)        x[i]=x[i-1]*(4*i-2)/(i+1);    while(scanf("%d",&n)==1 && n!=-1)    {        x[n].print();    }}

2)java版

BigInteger类:
abs() 返回其值是此BigInteger的绝对值的BigInteger。
compareTo(BigInteger val) 将此BigInteger与指定的BigInteger进行比较。
divide(BigInteger val) 返回其值为 (this / val) 的BigInteger。
pow(int exponent) 返回其值为 (thisexponent) 的BigInteger。
multiply(BigInteger val) 返回其值为 (this * val) 的BigInteger。
gcd(BigInteger val) 返回一个 BigInteger,其值是 abs(this) 和 abs(val) 的最大公约数。
subtract(BigInteger val) 返回其值为 (this - val) 的 BigInteger。
BigDecimal类:
BigDecimal(String val)
将 BigDecimal 的字符串表示形式转换为 BigDecimal。
abs()
返回 BigDecimal,其值为此 BigDecimal 的绝对值,其标度为 this.scale()。
add(BigDecimal augend)
返回一个 BigDecimal,其值为 (this + augend),其标度为 max(this.scale(), augend.scale())。
compareTo(BigDecimal val)
将此 BigDecimal 与指定的 BigDecimal 比较。
divide(BigDecimal divisor, int scale, int roundingMode)
返回一个 BigDecimal,其值为 (this / divisor),其标度为指定标度。
RoundingMode
CEILING
向正无限大方向舍入的舍入模式。
DOWN
向零方向舍入的舍入模式。
FLOOR
向负无限大方向舍入的舍入模式。
HALF_DOWN
向最接近数字方向舍入的舍入模式,如果与两个相邻数字的距离相等,则向下舍入。
HALF_EVEN
向最接近数字方向舍入的舍入模式,如果与两个相邻数字的距离相等,则向相邻的偶数舍入。
HALF_UP
向最接近数字方向舍入的舍入模式,如果与两个相邻数字的距离相等,则向上舍入。
UNNECESSARY
用于断言请求的操作具有精确结果的舍入模式,因此不需要舍入。
UP
远离零方向舍入的舍入模式。
setScale(int newScale, RoundingMode roundingMode)
返回 BigDecimal,其标度为指定值,其非标度值通过此 BigDecimal 的非标度值乘以或除以十的适当次幂来确定,以维护其总值。
subtract(BigDecimal subtrahend)
返回一个 BigDecimal,其值为 (this - subtrahend),其标度为 max(this.scale(), subtrahend.scale())。
divide(BigDecimal divisor, RoundingMode roundingMode)
返回一个 BigDecimal,其值为 (this / divisor),其标度为 this.scale()。
更多的函数请参考javaAPI文档。

示例:

import java.util.*;import java.math.*;public class Main{    public static void main(String[] args) {        Scanner cin = new Scanner (System.in);        int cc = cin.nextInt();        int cas = 1;        for (int i=0;i<cc;i++){            BigInteger a = cin.nextBigInteger();            BigInteger b = cin.nextBigInteger();            BigInteger c = a .add( b );            System.out.println("Case " + cas +":");            cas++;            System.out.print(a+" + " + b +" = ");            System.out.println(c);            if (i<cc-1)                System.out.println();        }    }}

3)python版(待续)

gmpy

2.Trie

#include <iostream>#include <fstream>#include <cstring>#include <cstdio>#include <math.h>#include <queue>#include <vector>#include <algorithm>#include <map>#include <set>using namespace std;typedef long long LL;const int N = 32000005;const int M = 1000005;const int INF = 0x3f3f3f3f;int n,m,k;LL a;struct Trie{    LL v;    int nxt[3];    void init(){        v=-1;        memset(nxt,-1,sizeof(nxt));    }};Trie trie[N];int sz;LL ans;LL l,r;void ini(){    sz=1;    trie[0].init();}void insert(LL x,LL ip){    int pos=0;    for (int i=32;i>=0;i--)     {        int c;        c = (x&(1LL<<i)) ? 1 : 0;        if (trie[pos].nxt[c]==-1)        {            trie[pos].nxt[c]=sz;            trie[sz++].init();        }        pos=trie[pos].nxt[c];    }    trie[pos].v=ip;}void query(LL x,LL ip){    int pos=0;    LL res=0;    for (int i=32;i>=0;i--)    {        int c = (x&(1LL<<i)) ? 1 : 0;        if (trie[pos].nxt[c^1]!=-1)        {            pos=trie[pos].nxt[c^1];            res=(res|1)<<1;        }        else        {            pos=trie[pos].nxt[c];            res=(res|0)<<1;        }    }    res>>=1;    if (ans<=res)    {        if (ans==res)        {            if (min(ip,trie[pos].v)+1<l)            {                l=min(ip,trie[pos].v)+1;                r=max(ip,trie[pos].v);            }        }        else        {            ans=res;            l=min(ip,trie[pos].v)+1;            r=max(ip,trie[pos].v);        }    }}LL s[N];int main(){    int cc;    int cas=1;    scanf("%d",&cc);    while (cc--)    {        ans=0;        l=INF,r=0;        ini();        scanf("%d",&n);        s[0]=0;        for (int i=1;i<=n;i++)        {            scanf("%lld",&a);            s[i]=s[i-1]^a;            insert(s[i],i);            if (ans<s[i])            {                l=1;                r=i;                ans=s[i];            }        }        printf("Case #%d:\n", cas++);        for (int i=1;i<=n;i++)            query(s[i],i);        printf("%lld %lld\n", l,r);    }    return 0;}

3.AC自动机

/* AC + 高斯消元 骰子串匹配概率*/#include <iostream>#include <string.h>#include <math.h>#include <algorithm>#include <cstdio>#include <iomanip>#include <queue>#include <map>using namespace std;typedef long long LL;const int N = 557;const double eps = 0.0001;int n,m, cc;int s[N][10], d[N];double p[N][N];int ans[N];struct trie{    int sz,val[N],fail[N],tr[N][10];    void ini()    {        sz=0;        memset(tr,0,sizeof(tr));        memset(val,0,sizeof(val));        memset(fail,0,sizeof(fail));    }    int insert(int *ch)    {        int w=0;        while (*ch!=-1&&tr[w][*ch])            w=tr[w][*ch],ch++;        while (*ch!=-1)            tr[w][*ch]=++sz,ch++,w=sz;        val[w]=1;        return w;    }    void bulid()    {        queue <int> q;        for (int i=0;i<6;i++)            if (tr[0][i])                q.push(tr[0][i]);        while (!q.empty())        {            int now=q.front();            q.pop();            if (val[now])                continue;            for (int i=0;i<6;i++)            {                if (tr[now][i])                {                    fail[tr[now][i]]=tr[fail[now]][i];                    q.push(tr[now][i]);                }                else                     tr[now][i]=tr[fail[now]][i];            }        }    }}AC;void gauss(int n){    int mi;    double h;    for (int i=1;i<=n;i++)    {        mi=i;        for (int j=i;j<=n;j++)            if (fabs(p[j][i])>fabs(p[mi][j]))                mi=j;        if (fabs(p[mi][i])<eps)            return ;        if (mi!=i)            for (int j=i;j<=n+1;j++)                 swap(p[i][j],p[mi][j]);        h=p[i][i];        for (int j=i;j<=n+1;j++)            p[i][j]/=h;        for (int j=1;j<=n;j++)            if (j!=i)            {                h-=p[j][i]/p[i][i];                for (int k=1;k<=n+1;k++)                    p[j][k]+=h*p[i][k];            }    }}int main(){    int cas=1;    scanf("%d",&cc);    while (cc--)    {        scanf("%d%d",&n,&m);        AC.ini();        for (int i=0;i<n;i++)        {            for (int j=0;j<m;j++)                scanf("%d",&d[j]),d[j]--;            d[m]=-1;            ans[i]=AC.insert(d);        }        AC.bulid();        // for (int i=0;i<AC.sz;i++)        // {        //     for (int j=0;j<6;j++)        //         cout<<AC.tr[i][j]<<" ";        //     cout<<endl;        // }        for (int i=0;i<AC.sz;i++)        {            d[i]=0;            for (int j=0;j<6;j++)                if (AC.tr[i][j])                    d[i]++;        }        memset(p,0,sizeof(p));        for (int i=1;i<=AC.sz;i++)            p[i][i]+=1.0;        for (int i=0;i<6;i++)            if (AC.tr[0][i])                p[AC.tr[0][i]][AC.sz+1]+=1.0/d[0];        for (int i=1;i<AC.sz;i++)        {            for (int j=0;j<6;j++)                if (AC.tr[i][j])                    p[AC.tr[i][j]][i]-=1.0/6.0;            if (d[i]!=6&&AC.val[i])            {                for (int j=0;j<6;j++)                    if (AC.tr[0][j])                        p[AC.tr[0][j]][i]-=1.0*(6-d[i])/(6.0*d[0]);            }        }        gauss(AC.sz);        for (int i=1;i<n;i++)            printf("%.6f\n",p[ans[i]][AC.sz+1]);        printf("%.6f\n",p[ans[n]][AC.sz+1]);    }    return 0;}

4.KD_tree

/* 最近点距离*/#include <cstdio>#include <math.h>#include <iostream>#include <algorithm>#include <string.h>#include <queue>#include <set>#include <map>using namespace std;typedef long long LL;const int N = 1000007;const int M = 100005;const int INF = 0x3f3f3f3f;const int MOD = 1000000007;int n,m;int root;int ans;int now;int ql,qr;struct nd{    int ma[2],mi[2];    int d[2];    int l,r;}t[N<<1];inline int getint(){       int w=0,q=0;       char c=getchar();       while((c<'0' || c>'9') && c!='-') c=getchar();       if (c=='-')  q=1, c=getchar();       while (c>='0' && c<='9') w=w*10+c-'0', c=getchar();       return q ? -w : w;}bool cmp(nd a,nd b){    if (a.d[now] == b.d[now])        return a.d[!now]<b.d[!now];    return a.d[now]<b.d[now];}void kd_update(int k){    if (t[k].l)    {        if (t[t[k].l].ma[0] > t[k].ma[0]) t[k].ma[0]=t[t[k].l].ma[0];        if (t[t[k].l].ma[1] > t[k].ma[1]) t[k].ma[1]=t[t[k].l].ma[1];        if (t[t[k].l].mi[0] < t[k].mi[0]) t[k].mi[0]=t[t[k].l].mi[0];        if (t[t[k].l].mi[1] < t[k].mi[1]) t[k].mi[1]=t[t[k].l].mi[1];    }    if (t[k].r)    {        if (t[t[k].r].ma[0] > t[k].ma[0]) t[k].ma[0]=t[t[k].r].ma[0];        if (t[t[k].r].ma[1] > t[k].ma[1]) t[k].ma[1]=t[t[k].r].ma[1];        if (t[t[k].r].mi[0] < t[k].mi[0]) t[k].mi[0]=t[t[k].r].mi[0];        if (t[t[k].r].mi[1] < t[k].mi[1]) t[k].mi[1]=t[t[k].r].mi[1];    }}int kd_build(int l,int r,int k){    int mid=(l+r)>>1;    now=k;    nth_element(t+l+1,t+mid+1,t+r+1,cmp);    if (l!=mid)        t[mid].l=kd_build(l,mid-1,!k);    if (r!=mid)        t[mid].r=kd_build(mid+1,r,!k);    t[mid].ma[0]=t[mid].mi[0]=t[mid].d[0];    t[mid].ma[1]=t[mid].mi[1]=t[mid].d[1];    kd_update(mid);    return mid;}int dis(int k){    int res=0;    if (ql<t[k].mi[0]) res+=t[k].mi[0]-ql;    if (ql>t[k].ma[0]) res+=ql-t[k].ma[0];    if (qr<t[k].mi[1]) res+=t[k].mi[1]-qr;    if (qr>t[k].ma[1]) res+=qr-t[k].ma[1];    return res;}void kd_query(int k){    int dl,dr,d0;    d0=abs(t[k].d[0]-ql)+abs(t[k].d[1]-qr);    if (d0<ans)        ans=d0;    if (t[k].l) dl=dis(t[k].l); else dl=INF;    if (t[k].r) dr=dis(t[k].r); else dr=INF;    if (dl<dr)    {        if (dl<ans)            kd_query(t[k].l);        if (dr<ans)            kd_query(t[k].r);    }    else    {        if (dr<ans)            kd_query(t[k].r);        if (dl<ans)            kd_query(t[k].l);    }}void kd_insert(int k){    int p=root,D=0;    while (1)    {        if (t[k].ma[0]>t[p].ma[0]) t[p].ma[0]=t[k].ma[0];        if (t[k].ma[1]>t[p].ma[1]) t[p].ma[1]=t[k].ma[1];        if (t[k].mi[0]<t[p].mi[0]) t[p].mi[0]=t[k].mi[0];        if (t[k].mi[1]<t[p].mi[1]) t[p].mi[1]=t[k].mi[1];        if (t[k].d[D]>=t[p].d[D])        {            if (!t[p].r)            {                t[p].r=k;                return;            }            else                p=t[p].r;        }        else        {            if (!t[p].l)            {                t[p].l=k;                return;            }            else                p=t[p].l;        }        D=!D;    }}int main(){    scanf("%d%d",&n,&m);    {        for (int i=1;i<=n;i++)            scanf("%d%d",&t[i].d[0],&t[i].d[1]);        root=kd_build(1,n,0);        int x,y,z;        for (int i=0;i<m;i++)        {            scanf("%d%d%d",&x,&y,&z);            if (x==1)            {                n++;                t[n].ma[0]=y;                t[n].mi[0]=y;                t[n].d[0]=y;                t[n].ma[1]=z;                t[n].mi[1]=z;                t[n].d[1]=z;                kd_insert(n);            }            else            {                ans=INF;                ql=y;                qr=z;                kd_query(root);                printf("%d\n", ans);            }        }    }    return 0;}

5.KMP

#include <iostream>#include <cstdio>#include <algorithm>#include <math.h>#include <vector>#include <string.h>#include <iomanip>#include <set>#include <string>#include <map>#include <queue>using namespace std;typedef long long LL;const int N = 1000020 ;const int MOD = 998244353 ;const int INF = 0x3f3f3f3f;const double Pi = acos(-1);int n,m,p,cc;int s[N],t[N];int nextt[N];int main(){    scanf("%d",&cc);    int cas=1;    while(cc--)    {        scanf("%d%d%d",&n,&m,&p);        for (int i=0;i<n;i++)            scanf("%d",&s[i]);        for (int i=0;i<m;i++)            scanf("%d",&t[i]);        //Next Array        nextt[0]=0;        nextt[1]=0;        for (int i=1;i<m;i++)        {            int j=nextt[i];            while (j && t[i]!=t[j])                j=nextt[j];            nextt[i+1] = t[i] == t[j] ? j+1 : 0 ;        }        // Find        int ans=0;        int j=0;        for (int sta=0;sta<p;sta++)            for (int i=sta,j=0;i<n;i+=p)            {                while (j && s[i]!=t[j])                    j=nextt[j];                if (s[i]==t[j])                    j++;                if (j==m)                {                    // printf("bug: %d\n",i-m+1);  // Found!                    ans++;                }            }        printf("Case #%d: %d\n",cas++,ans);        memset(nextt,0,sizeof(nextt));        memset(s,0,sizeof(s));        memset(t,0,sizeof(t));    }    return 0;}

6.半平面交

//多边形的核#include <stdio.h>#include <string.h>#include <cstdio>#include <algorithm>#include <iostream>#include <math.h>using namespace std;const int N = 300005;const double EXP = 1e-8;typedef long long LL;struct point{    double x , y ;}p[N];struct line{    point a,b;    double angle;}l[N];int cas,n,top,bot,order[N],ln,dq[N];double abs(double a){    if (a<0)        return -a;    return a;}int dblcmp(double k){    if (abs(k)<EXP)        return 0;    return k>0?1:-1;}double det(point p0,point p1,point p2){    return (p1.x-p0.x)*(p2.y-p0.y)-(p1.y-p0.y)*(p2.x-p0.x);}bool cmp(int a,int b){    int d = dblcmp(l[a].angle-l[b].angle);    if (d==0)        return dblcmp(det(l[a].a,l[b].a,l[b].b))<0;  //  逆时针输入(取左侧)时为">"    return d<0;}void getIntersect (line l1,line l2,point &p){    double d1,d2;    d1=det(l2.a,l1.b,l1.a);    d2=det(l1.b,l2.b,l1.a);    p.x=(l2.a.x*d2+l2.b.x*d1)/(d2+d1);    p.y=(l2.a.y*d2+l2.b.y*d1)/(d2+d1);}bool judge (line l0,line l1,line l2){    point p;    getIntersect(l1,l2,p);    return dblcmp(det(p,l0.a,l0.b))>0;      //  逆时针输入(即取左侧)时为"<"}void addline(double x1,double y1,double x2,double y2){    l[ln].a.x=x1;    l[ln].a.y=y1;    l[ln].b.x=x2;    l[ln].b.y=y2;    l[ln].angle=atan2(y2-y1,x2-x1);    order[ln]=ln;    ln++;}void halfPlaneIntersection(){    int i,j;    sort(order,order+ln,cmp);    for (i=1,j=0;i<ln;i++)        if (dblcmp(l[order[i]].angle-l[order[j]].angle)>0)            order[++j]=order[i];    ln=j+1;    dq[0]=order[0];    dq[1]=order[1];    bot=0;    top=1;    for (i=2;i<ln;i++)    {        while (bot<top&&judge(l[order[i]],l[dq[top-1]],l[dq[top]]))            top--;        while (bot<top&&judge(l[order[i]],l[dq[bot+1]],l[dq[bot]]))            bot++;        dq[++top]=order[i];    }    while (bot<top&&judge(l[order[bot]],l[dq[top-1]],l[dq[top]]))        top--;    while (bot<top&&judge(l[order[top]],l[dq[bot+1]],l[dq[bot]]))        bot++;}bool isCore(){    if (top-bot>1)        return true;    return false;}int main (){    int i;    scanf ("%d",&cas);    while (cas--)    {        scanf ("%d",&n);        for (i=0;i<n;i++)            scanf("%lf%lf",&p[i].x,&p[i].y);        for (ln=i=0;i<n-1;i++)            addline(p[i].x,p[i].y,p[i+1].x,p[i+1].y);        addline(p[i].x,p[i].y,p[0].x,p[0].y);        halfPlaneIntersection();        if (isCore())            printf("YES\n");        else            printf("NO\n");    }return 0 ;}

7.大素数(论文题,Meisell-Lehmer , 范围~1e11)

//Meisell-Lehmer//G++ 218ms 43252k#include<cstdio>#include<cmath>using namespace std;#define LL long longconst int N = 5e6 + 2;bool np[N];int prime[N], pi[N];int getprime(){    int cnt = 0;    np[0] = np[1] = true;    pi[0] = pi[1] = 0;    for(int i = 2; i < N; ++i)    {        if(!np[i]) prime[++cnt] = i;        pi[i] = cnt;        for(int j = 1; j <= cnt && i * prime[j] < N; ++j)        {            np[i * prime[j]] = true;            if(i % prime[j] == 0)   break;        }    }    return cnt;}const int M = 7;const int PM = 2 * 3 * 5 * 7 * 11 * 13 * 17;int phi[PM + 1][M + 1], sz[M + 1];void init(){    getprime();    sz[0] = 1;    for(int i = 0; i <= PM; ++i)  phi[i][0] = i;    for(int i = 1; i <= M; ++i)    {        sz[i] = prime[i] * sz[i - 1];        for(int j = 1; j <= PM; ++j) phi[j][i] = phi[j][i - 1] - phi[j / prime[i]][i - 1];    }}int sqrt2(LL x){    LL r = (LL)sqrt(x - 0.1);    while(r * r <= x)   ++r;    return int(r - 1);}int sqrt3(LL x){    LL r = (LL)cbrt(x - 0.1);    while(r * r * r <= x)   ++r;    return int(r - 1);}LL getphi(LL x, int s){    if(s == 0)  return x;    if(s <= M)  return phi[x % sz[s]][s] + (x / sz[s]) * phi[sz[s]][s];    if(x <= prime[s]*prime[s])   return pi[x] - s + 1;    if(x <= prime[s]*prime[s]*prime[s] && x < N)    {        int s2x = pi[sqrt2(x)];        LL ans = pi[x] - (s2x + s - 2) * (s2x - s + 1) / 2;        for(int i = s + 1; i <= s2x; ++i) ans += pi[x / prime[i]];        return ans;    }    return getphi(x, s - 1) - getphi(x / prime[s], s - 1);}LL getpi(LL x){    if(x < N)   return pi[x];    LL ans = getphi(x, pi[sqrt3(x)]) + pi[sqrt3(x)] - 1;    for(int i = pi[sqrt3(x)] + 1, ed = pi[sqrt2(x)]; i <= ed; ++i) ans -= getpi(x / prime[i]) - i + 1;    return ans;}LL lehmer_pi(LL x){    if(x < N)   return pi[x];    int a = (int)lehmer_pi(sqrt2(sqrt2(x)));    int b = (int)lehmer_pi(sqrt2(x));    int c = (int)lehmer_pi(sqrt3(x));    LL sum = getphi(x, a) +(LL)(b + a - 2) * (b - a + 1) / 2;    for (int i = a + 1; i <= b; i++)    {        LL w = x / prime[i];        sum -= lehmer_pi(w);        if (i > c) continue;        LL lim = lehmer_pi(sqrt2(w));        for (int j = i; j <= lim; j++) sum -= lehmer_pi(w / prime[j]) - (j - 1);    }    return sum;}int main(){    init();    LL n;    while(~scanf("%lld",&n))    {        printf("%lld\n",lehmer_pi(n));    }    return 0;}

8.二分图最大匹配(匈牙利算法)

#include<iostream>#include<cstdio>#include<vector>#include<string.h>using namespace std;#define M 10005int n,k,a,b;int match[M],used[M];vector <int> G[M];void add(int a,int b){    G[a].push_back(b);    G[b].push_back(a);}int dfs(int v){    used[v]=1;    for (int i=0;i<G[v].size();i++)    {        int u=G[v][i];        int w=match[u];        if (w<0||!used[w]&&dfs(w))        {            match[u]=v;            match[v]=u;            return 1;        }    }    return 0;}int bi_match(){    int ans=0;    memset(match,-1,sizeof(match));    for (int v=0;v<n;v++)    {        memset(used,0,sizeof(used));        if (dfs(v))            ans++;    }    return ans;}int main(){    scanf("%d%d",&n,&k);    int v=n*2;    for (int i=0;i<k;i++)    {        scanf("%d%d",&a,&b);        add(a-1,n+b-1);    }    printf("%d",bi_match());    return 0;}

9.费用流

1)基于spfa的MCMF

#include <iostream>#include <string.h>#include <stdio.h>#include <algorithm>#include <queue>#define V 10100#define E 1000100#define inf 99999999using namespace std;int vis[V];int dist[V];int pre[V];struct Edge{    int u,v,c,cost,next;}edge[E];int head[V],cnt;void init(){    cnt=0;    memset(head,-1,sizeof(head));}void addedge(int u,int v,int c,int cost){    edge[cnt].u=u;edge[cnt].v=v;edge[cnt].cost=cost;    edge[cnt].c=c;edge[cnt].next=head[u];head[u]=cnt++;    edge[cnt].u=v;edge[cnt].v=u;edge[cnt].cost=-cost;    edge[cnt].c=0;edge[cnt].next=head[v];head[v]=cnt++;}bool spfa(int begin,int end){    int u,v;    queue<int> q;    for(int i=0;i<=end+2;i++){        pre[i]=-1;        vis[i]=0;        dist[i]=inf;    }    vis[begin]=1;    dist[begin]=0;    q.push(begin);    while(!q.empty()){        u=q.front();        q.pop();        vis[u]=0;        for(int i=head[u];i!=-1;i=edge[i].next){            if(edge[i].c>0){                v=edge[i].v;                if(dist[v]>dist[u]+edge[i].cost){                    dist[v]=dist[u]+edge[i].cost;                    pre[v]=i;                    if(!vis[v]){                        vis[v]=true;                        q.push(v);                    }                }            }        }    }    return dist[end]!=inf;}int MCMF(int begin,int end){    int ans=0,flow;    int flow_sum=0;    while(spfa(begin,end)){        flow=inf;        for(int i=pre[end];i!=-1;i=pre[edge[i].u])            if(edge[i].c<flow)                flow=edge[i].c;        for(int i=pre[end];i!=-1;i=pre[edge[i].u]){            edge[i].c-=flow;            edge[i^1].c+=flow;        }        ans+=dist[end];        flow_sum += flow;    }    //cout << flow_sum << endl;    return ans;}int main(){    //freopen("in.txt","r",stdin);    int n,m,a,b,c;    while(scanf("%d%d",&n,&m)!=EOF){        init();        addedge(0,1,2,0);        addedge(n,n+1,2,0);        for(int i=1;i<=m;i++){            scanf("%d%d%d",&a,&b,&c);            addedge(a,b,1,c);            addedge(b,a,1,c);        }        printf("%d\n",MCMF(0,n+1));    }    return 0;} 

2)ZKW费用流(适合 稠密图二分图)[效率会近高于之前10倍]

//不资瓷负权#include <iostream>  #include <algorithm>  #include <cstring>  #include <string>  #include <cstdio>  #include <cmath>  #include <queue>  #include <map>  #include <set>  #define eps 1e-5  #define MAXN 222  #define MAXM 55555  #define INF 1000000007  using namespace std;  struct EDGE  {      int cost, cap, v;      int next, re;  }edge[MAXM];  int head[MAXN], e;  int vis[MAXN];  int ans, cost, src, des, n;  void init()  {      memset(head, -1, sizeof(head));      e = 0;      ans = cost = 0;  }  void add(int u, int v, int cap, int cost)  {      edge[e].v = v;      edge[e].cap = cap;      edge[e].cost = cost;      edge[e].re = e + 1;      edge[e].next = head[u];      head[u] = e++;      edge[e].v = u;      edge[e].cap = 0;      edge[e].cost = -cost;      edge[e].re = e - 1;      edge[e].next = head[v];      head[v] = e++;  }  int aug(int u, int f)  {      if(u == des)      {          ans += cost * f;          return f;      }      vis[u] = 1;      int tmp = f;      for(int i = head[u]; i != -1; i = edge[i].next)          if(edge[i].cap && !edge[i].cost && !vis[edge[i].v])          {              int delta = aug(edge[i].v, tmp < edge[i].cap ? tmp : edge[i].cap);              edge[i].cap -= delta;              edge[edge[i].re].cap += delta;              tmp -= delta;              if(!tmp) return f;          }      return f - tmp;  }  bool modlabel()  {      int delta = INF;      for(int u = 1; u <= n; u++)          if(vis[u])              for(int i = head[u]; i != -1; i = edge[i].next)                  if(edge[i].cap && !vis[edge[i].v] && edge[i].cost < delta) delta = edge[i].cost;      if(delta == INF) return false;      for(int u = 1; u <= n; u++)          if(vis[u])              for(int i = head[u]; i != -1; i = edge[i].next)                  edge[i].cost -= delta, edge[edge[i].re].cost += delta;      cost += delta;      return true;  }  void costflow()  {      do      {          do          {              memset(vis, 0, sizeof(vis));          }while(aug(src, INF));      }while(modlabel());  }  int nt, m;  struct point  {      int x, y;  }p[MAXN], h[MAXN];  int d[MAXN][MAXN];  char s[MAXN][MAXN];  int main()  {      while(scanf("%d%d", &m, &nt) != EOF)      {          if(m == 0 && nt == 0) break;          for(int i = 0; i < m; i++)              scanf("%s", s[i]);          int hcnt = 0, pcnt = 0;          for(int i = 0; i < m; i++)              for(int j = 0; j < nt; j++)              {                  if(s[i][j] == 'H')                  {                      hcnt++;                      h[hcnt].x = i;                      h[hcnt].y = j;                  }                  else if(s[i][j] == 'm')                  {                      pcnt++;                      p[pcnt].x = i;                      p[pcnt].y = j;                  }              }          for(int i = 1; i <= pcnt; i++)              for(int j = 1; j <= hcnt; j++)                  d[i][j] = abs(p[i].x - h[j].x) + abs(p[i].y - h[j].y);          init();          n = hcnt + pcnt + 2;          src = hcnt + pcnt + 1;          des = n;          for(int i = 1; i <= pcnt; i++)              for(int j = 1; j <= hcnt; j++)                  add(i, j + pcnt, 1, d[i][j]);          for(int i = 1; i <= pcnt; i++)              add(src, i, 1, 0);          for(int i = 1; i <= hcnt; i++)              add(i + pcnt, des, 1, 0);          costflow();          printf("%d\n", ans);      }      return 0;  }  

10.最大流

1)Dinic

#include <iostream>#include <vector>#include <algorithm>#include <stack>#include <string>#include <cstdio>#include <set>#include <string.h>#include <vector>#include <queue>using namespace std;typedef long long LL;const int N = 305;const int INF = (1<<20);int n,t,a,b,c,m,k;int map[N][N],dp[N][N];struct edge {    int to,cap,rev;};vector <edge> G[N];int level [N],iter[N];int used[N];void add(int from,int to,int cap){    G[from].push_back((edge){to,cap,G[to].size()});    G[to].push_back((edge){from,0,G[from].size()-1});}void bfs (int s){    memset(level,-1,sizeof(level));    queue <int> que;    level[s]=0;    que.push(s);    while (!que.empty())    {        int v=que.front();        que.pop();        for (int i=0;i<G[v].size();i++)        {            edge &e= G[v][i];            if (e.cap>0&&level[e.to]<0)            {                level[e.to]=level[v]+1;                que.push(e.to);            }        }    }}int dfs(int v,int t,int f){    if (v==t)        return f;    for (int &i=iter[v];i<G[v].size();i++)    {        edge &e=G[v][i];        if (e.cap>0&&level[v]<level[e.to])        {            int d=dfs(e.to,t,min(f,e.cap));            if (d>0)            {                e.cap-=d;                G[e.to][e.rev].cap+=d;                return d;            }        }    }    return 0;}int max_flow(int s,int t){    int flow=0;    for (;;)    {        bfs(s);        if (level[t]<0)            return flow;        memset(iter,0,sizeof(iter));        int f;        while ((f=dfs(s,t,INF))>0)            flow+=f;    }}void ini(){    for (int i=0;i<=k+c+2;i++)        G[i].clear();}int main(){    scanf("%d%d%d",&k,&c,&m);    {        int S=0,T=k+c+2;        n=k+c;        for (int i=1;i<=k+c;i++)            for (int j=1;j<=k+c;j++)            {                scanf("%d",&map[i][j]);                dp[i][j]=map[i][j]==0?INF:map[i][j];            }        int mi=(INF),ma=0;        for (int kk=1;kk<=n;kk++)            for (int j=1;j<=n;j++)                for (int i=1;i<=n;i++)                {                    dp[i][j]=min(dp[i][j],dp[i][kk]+dp[kk][j]);                }               int l=0,r=200*n,mid;        while (l<r)        {            mid=(l+r)>>1;            ini();            for (int i=1;i<=k;i++)            {                add(S,i,m);                for (int j=k+1;j<=c+k;j++)                    if (dp[i][j]<=mid)                    {                        add(i,j,1);                    }            }            for (int j=k+1;j<=c+k;j++)                add(j,T,1);            int ans=max_flow(S,T);            if (ans==c)                r=mid;            else                l=mid+1;        }        printf("%d\n",l);    }    return 0;}

2)SAP

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<queue>using namespace std;#define MAXN 111#define inf 1<<30struct Edge{    int v,cap,next;}edge[MAXN*MAXN];int n,m,NE,NV;int head[MAXN];void Insert(int u,int v,int cap){    edge[NE].v=v;    edge[NE].cap=cap;    edge[NE].next=head[u];    head[u]=NE++;    edge[NE].v=u;    edge[NE].cap=0;    edge[NE].next=head[v];    head[v]=NE++;}int level[MAXN],gap[MAXN];void bfs(int vt){    memset(level,-1,sizeof(level));    memset(gap,0,sizeof(gap));    level[vt]=0;    gap[level[vt]]++;    queue<int>que;    que.push(vt);    while(!que.empty()){        int u=que.front();        que.pop();        for(int i=head[u];i!=-1;i=edge[i].next){            int v=edge[i].v;            if(level[v]!=-1)continue;            level[v]=level[u]+1;            gap[level[v]]++;            que.push(v);        }    }}int pre[MAXN],cur[MAXN];int SAP(int vs,int vt){    bfs(vt);    memset(pre,-1,sizeof(pre));    memcpy(cur,head,sizeof(head));    int maxflow=0,aug=inf;    int u=pre[vs]=vs;    gap[0]=NV;    while(level[vs]<NV){        bool flag=false;        for(int &i=cur[u];i!=-1;i=edge[i].next){            int v=edge[i].v;            if(edge[i].cap>0&&level[u]==level[v]+1){                flag=true;                pre[v]=u;                u=v;                aug=min(aug,edge[i].cap);                if(v==vt){                    maxflow+=aug;                    for(u=pre[v];v!=vs;v=u,u=pre[u]){                        edge[cur[u]].cap-=aug;                        edge[cur[u]^1].cap+=aug;                    }                    aug=inf;                }                break;            }        }        if(flag)continue;        int minlevel=NV;        for(int i=head[u];i!=-1;i=edge[i].next){            int v=edge[i].v;            if(edge[i].cap>0&&level[v]<minlevel){                minlevel=level[v];                cur[u]=i;            }        }        if(--gap[level[u]]==0)break;        level[u]=minlevel+1;        gap[level[u]]++;        u=pre[u];    }    return maxflow;}bool map[MAXN][MAXN];void Build(){    NE=0;    memset(head,-1,sizeof(head));    for(int i=0;i<n;i++){        for(int j=0;j<n;j++){            if(i==j)                Insert(i,i+n,1);            else if(map[i][j])                Insert(i+n,j,inf);        }    }}int main(){ //   freopen("1.txt","r",stdin);    int u,v,ans;    while(~scanf("%d%d",&n,&m)){        NV=2*n;        memset(map,false,sizeof(map));        while(m--){            scanf(" (%d,%d)",&u,&v);            map[u][v]=map[v][u]=true;        }        ans=n;        for(int vs=0;vs<n;vs++){            for(int vt=vs+1;vt<n;vt++){                Build();                int tp=SAP(vs+n,vt);                //cout<<"bug: "<<tp<<endl;                ans=min(ans,tp);            }        }        //if(ans>=n)ans=n;        printf("%d\n",ans);    }    return 0;}

11.后缀数组

1)倍增法

//包含c的不重复子串个数#include <stdio.h>#include <stdlib.h>#include <string.h>#include <iostream>#include <algorithm>using namespace std;typedef long long ll;const int inf=0x3f3f3f3f;const int MAXN=100010;int sa[MAXN];int t1[MAXN],t2[MAXN],c[MAXN];int Rank[MAXN],height[MAXN];/*       sa[1~~n]为有效值  sa[i]=a则代表排在第 i 位的是第a个后缀。  a属于[0~~n-1]       rank[0~~n-1]是有效值  rank[i]=b则代表第 i 个后缀排在第b位   b属于[1~~n]       height[2~~n]是有效值  height[i]=c 则代表排在第 i 位的后缀和排在第i-1的后缀的最长前缀长度是c。*/void construct_sa(int s[],int n,int m){    int i,j,p,*x=t1,*y=t2;    for(i=0;i<m;i++)c[i]=0;    for(i=0;i<n;i++)c[x[i]=s[i]]++;    for(i=1;i<m;i++)c[i]+=c[i-1];    for(i=n-1;i>=0;i--)sa[--c[x[i]]]=i;    for(j=1;j<=n;j<<=1){        p=0;        for(i=n-j;i<n;i++)y[p++]=i;        for(i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j;        for(i=0;i<m;i++)c[i]=0;        for(i=0;i<n;i++)c[x[y[i]]]++;        for(i=1;i<m;i++)c[i]+=c[i-1];        for(i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i];        swap(x,y);        p=1;x[sa[0]]=0;        for(i=1;i<n;i++)            x[sa[i]]=y[sa[i-1]]==y[sa[i]] && y[sa[i-1]+j]==y[sa[i]+j]?p-1:p++;        if(p>=n)break;        m=p;    }}void construct_lcp(int s[],int n){    int k=0;    for(int i=0;i<=n;i++) Rank[sa[i]]=i;    for(int i=0;i<n;i++){        if(k)k--;        int j=sa[Rank[i]-1];        while(s[i+k]==s[j+k])k++;        height[Rank[i]]=k;    }}int fvis[MAXN],pr[MAXN],s[MAXN];char str[MAXN];int main(){    int T,cas=1;    char ch[10];    scanf("%d",&T);    while(T--){        scanf("%s",ch);        scanf("%s",str);        int n=strlen(str),flag=0,fpr;        for(int i=0;i<=n;i++) s[i]=str[i];        memset(fvis,0,sizeof(fvis));        memset(pr,0,sizeof(pr));        for(int i=n-1;i>=0;i--){            if(str[i]==ch[0]){                flag=1;fpr=i;            }            if(flag) fvis[i]=1,pr[i]=fpr;        }        ll ans=0;        construct_sa(s,n+1,128);        construct_lcp(s,n);        for(int i=0;i<=n;i++){            if(fvis[sa[i]]) ans=ans+n-max((sa[i]+height[i]),pr[sa[i]]);        }        printf("Case #%d: %I64d\n",cas++,ans);    }    return 0;}

12.计算几何通用类

#include <iostream>#include <cstdio>#include <vector>#include <cmath>#include <algorithm>#define MAX 111116#define eps 1e-7using namespace std;int sgn(const double &x){ return x < -eps? -1 : (x > eps);}inline double sqr(const double &x){ return x * x;}inline int gcd(int a, int b){ return !b? a: gcd(b, a % b);}struct Point{    double x, y;    Point(){}    Point(const double &x, const double &y):x(x), y(y){}    Point operator -(const Point &a)const{ return Point(x - a.x, y - a.y); }    Point operator +(const Point &a)const{ return Point(x + a.x, y + a.y); }    Point operator * (const double &a)const{ return Point(x * a, y * a); }    Point operator / (const double &a)const{ return Point(x / a, y / a); }    friend double det(const Point &a, const Point &b){ return a.x * b.y - a.y * b.x;}    friend double dot(const Point &a, const Point &b){ return a.x * b.x + a.y * b.y;}    friend double dist(const Point &a, const Point &b){ return sqrt(sqr(a.x - b.x) + sqr(a.y - b.y));}    void in(){ scanf("%lf %lf", &x, &y); }    void out(){ printf("%.2f %.2f\n", x, y); }};struct Line{    Point s, t;    Line() {}    Line(const Point &s, const Point &t):s(s), t(t) {}    void in() { s.in(),t.in(); }    double pointDistLine(const Point &p)    {        if(sgn(dot(t - s, p - s)) < 0)return dist(p, s);        if(sgn(dot( s - t, p - t)) < 0)return dist(p, t);        return fabs(det(t - s, p - s)) / dist(s, t);    }    bool pointOnLine(const Point &p)    {        return sgn(det(t - s, p - s)) == 0 && sgn(dot(s - p, t - p)) <= 0;    }};struct Poly //多边形类{    vector<Point>a;    void in(const int &r)    {        a.resize(r);        for(int i = 0; i < r; i++) a[i].in();    }    //计算多边形的周长    double perimeter()    {        double sum=0;        int n=a.size();        for(int i=0;i<n;i++) sum+=dist(a[i],a[(i+1)%n]);        return sum;    }    //计算多边形的面积    double getDArea()    {        int n = a.size();        double ans = 0;        for(int i = 0; i < n; i++) ans += det(a[i], a[(i + 1)%n]);        return ans / 2;    }    //计算多边形的重心坐标    Point getMassCenter()    {        Point center(0, 0);        if(sgn(getDArea())==0) return center; //面积为0情况,当然这题说了面积不可能为0可不写        int n = a.size();        for(int i = 0; i < n; i++)            center =center + (a[i] + a[(i + 1) % n]) * det(a[i], a[(i + 1) % n]);        return center / getDArea() / 6;    }    //计算点t是否在多边形内,返回0指在外,1指在内,2指在边界上    int pointOnline(Point t)    {        int num=0,i,d1,d2,k,n=a.size();        for(i=0;i<n;i++)        {            Line line=Line(a[i],a[(i+1)%n]);            if(line.pointOnLine(t)) return 2;            k=sgn(det(a[(i+1)%n]-a[i],t-a[i]));            d1=sgn(a[i].y-t.y);            d2=sgn(a[(i+1)%n].y-t.y);            if(k>0&&d1<=0&&d2>0) num++;            if(k<0&&d2<=0&&d1>0) num--;        }        return num!=0;    }}poly;int main(){    int T;    cin>>T;    while(T--)    {        int n;        cin>>n;        poly.in(n);        poly.getMassCenter().out();    }    return 0;}

13.矩阵快速幂

#include <map>#include <set>#include <stack>#include <queue>#include <cmath>#include <string>#include <vector>#include <cstdio>#include <cctype>#include <cstring>#include <sstream>#include <cstdlib>#include <iostream>#include <algorithm>#pragma comment(linker,"/STACK:102400000,102400000")using namespace std;#define   MAX           200005#define   MAXN          1000005#define   maxnode       205#define   sigma_size    26#define   lson          l,m,rt<<1#define   rson          m+1,r,rt<<1|1#define   lrt           rt<<1#define   rrt           rt<<1|1#define   middle        int m=(r+l)>>1#define   LL            long long#define   ull           unsigned long long#define   mem(x,v)      memset(x,v,sizeof(x))#define   lowbit(x)     (x&-x)#define   pii           pair<int,int>#define   bits(a)       __builtin_popcount(a)#define   mk            make_pair#define   limit         10000//const int    prime = 999983;const int    INF   = 0x3f3f3f3f;const LL     INFF  = 0x3f3f;const double pi    = acos(-1.0);const double inf   = 1e18;const double eps   = 1e-4;const LL    mod    = 1e9+7;const ull    mx    = 133333331;struct Matrix{    int n;    LL maze[maxnode][maxnode];    void init(int n)    {        this->n = n;        mem(maze,0);    }    Matrix operator * (Matrix &rhs)    {        Matrix m;        m.init(n);        for(int i=0;i<n;i++)            for(int j=0;j<n;j++)                for(int k=0;k<n;k++)                    m.maze[i][j] = (m.maze[i][j] + maze[i][k] * rhs.maze[k][j])%mod;        return m;    }};int k;LL qpow(Matrix a,int n){    Matrix ans;    ans.init(a.n);    for(int i=0;i<ans.n;i++)        ans.maze[i][i] = 1;    while(n)    {        if(n&1) ans = ans * a;        a = a*a;        n >>= 1;    }    LL sum=0;    for (int i=0;i<ans.n;i++)    {        sum+=ans.maze[i][0];        sum%=mod;    }    return sum;}int main(){    int t;    scanf("%d",&t);    while(t--)    {        int n,m;        scanf("%d%d%d",&n,&m,&k);        Matrix A;        A.init(m+1);        for (int i=0;i<=m;i++)            A.maze[0][i]=k*k-k;        for (int i=0;i<=m;i++)            A.maze[i+1][i]=k;        LL ans=qpow(A,n);        A.init(m);        for (int i=0;i<m;i++)            A.maze[0][i]=k*k-k;        for (int i=0;i<m;i++)            A.maze[i+1][i]=k;        ans=(ans-qpow(A,n)+mod)%mod;        printf("%lld\n",ans);    }    return 0;}

14.快速傅里叶变换 (FFT)

/*    algorithm : High-Precision FFT*/#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>#define N 200005#define pi acos(-1.0) // PI值using namespace std;struct complex{    double r,i;    complex(double real=0.0,double image=0.0){        r=real; i=image;    }    // 以下为三种虚数运算的定义    complex operator + (const complex o){        return complex(r+o.r,i+o.i);    }    complex operator - (const complex o){        return complex(r-o.r,i-o.i);    }    complex operator * (const complex o){        return complex(r*o.r-i*o.i,r*o.i+i*o.r);    }}x1[N],x2[N];char a[N/2],b[N/2];int sum[N]; // 结果存在sum里void brc(complex *y,int l) // 二进制平摊反转置换 O(logn){    register int i,j,k;    for(i=1,j=l/2;i<l-1;i++)    {        if(i<j) swap(y[i],y[j]); // 交换互为下标反转的元素                                // i<j保证只交换一次        k=l/2;        while(j>=k) // 由最高位检索,遇1变0,遇0变1,跳出        {            j-=k;            k/=2;        }        if(j<k) j+=k;    }}void fft(complex *y,int l,double on) // FFT O(nlogn)                            // 其中on==1时为DFT,on==-1为IDFT{    register int h,i,j,k;    complex u,t;     brc(y,l); // 调用反转置换    for(h=2;h<=l;h<<=1) // 控制层数    {        // 初始化单位复根        complex wn(cos(on*2*pi/h),sin(on*2*pi/h));        for(j=0;j<l;j+=h) // 控制起始下标        {            complex w(1,0); // 初始化螺旋因子            for(k=j;k<j+h/2;k++) // 配对            {                u=y[k];                t=w*y[k+h/2];                y[k]=u+t;                y[k+h/2]=u-t;                w=w*wn; // 更新螺旋因子            } // 据说上面的操作叫蝴蝶操作…        }    }    if(on==-1)  for(i=0;i<l;i++)    y[i].r/=l; // IDFT}int main(void){    int l1,l2,l;    register int i;    while(scanf("%s%s",a,b)!=EOF)    {        l1=strlen(a);        l2=strlen(b);        l=1;        while(l<l1*2 || l<l2*2) l<<=1; // 将次数界变成2^n                                        // 配合二分与反转置换        for(i=0;i<l1;i++) // 倒置存入        {            x1[i].r=a[l1-i-1]-'0';            x1[i].i=0.0;        }        for(;i<l;i++)   x1[i].r=x1[i].i=0.0;        // 将多余次数界初始化为0        for(i=0;i<l2;i++)        {            x2[i].r=b[l2-i-1]-'0';            x2[i].i=0.0;        }        for(;i<l;i++)   x2[i].r=x2[i].i=0.0;        fft(x1,l,1); // DFT(a)        fft(x2,l,1); // DFT(b)        for(i=0;i<l;i++)    x1[i]=x1[i]*x2[i]; // 点乘结果存入a        fft(x1,l,-1); // IDFT(a*b)        for(i=0;i<l;i++)    sum[i]=x1[i].r+0.5; // 四舍五入        for(i=0;i<l;i++) // 进位        {            sum[i+1]+=sum[i]/10;            sum[i]%=10;        }        l=l1+l2-1;        while(sum[l]<=0 && l>0) l--; // 检索最高位        for(i=l;i>=0;i--)   putchar(sum[i]+'0'); // 倒序输出        putchar('\n');    }    return 0;}

15.快速数论变换 NTT

/*1.快速傅里叶变换适用于所有复数,但是存在精度问题。2.数论变换只能用于整数,但是速度会更快,可有准确求出卷积。3.数组常开n的4倍。*///NTTconst long long P = 50000000001507329LL; //190734863287 * 2 ^ 18 + 1const int G = 3;//P的原根long long wn[25];//此时应该大于18long long mul(long long x, long long y) {    return (x*y - (long long)(x / (long double)P*y + 1e-3) * P + P) % P;}//保证求余时两个数都是正的,处理精度问题long long qpow(long long x, long long k) {    long long ret = 1;    while(k) {        if(k & 1) ret = mul(ret, x);        k >>= 1;        x = mul(x, x);    }    return ret;}void getwn() {    for(int i = 1; i <= 18; ++i) {        int t = 1 << i;        wn[i] = qpow(G, (P - 1)/t);    }}int len;void change(long long y[], int len) {    for(int i = 1, j = len/2; i < len - 1; ++i) {        if(i < j) swap(y[i], y[j]);        int k = len/2;        while(j >= k) {            j -= k;            k /= 2;        }        j += k;    }}void NTT(long long y[], int on) {    change(y, len);    int id = 0;    for(int h = 2; h <= len; h <<= 1) {        ++id;        for(int j = 0; j < len; j += h) {            long long w = 1;            for(int k = j; k < j + h / 2; ++k) {                long long u = y[k];                long long t = mul(y[k+h/2], w);                y[k] = u + t;                if(y[k] >= P) y[k] -= P;                y[k+h/2] = u - t + P;                if(y[k+h/2] >= P) y[k+h/2] -= P;                w = mul(w, wn[id]);            }        }    }    if(on == -1) {        for(int i = 1; i < len / 2; ++i) swap(y[i], y[len-i]);        long long inv = qpow(len, P - 2);        for(int i = 0; i < len; ++i)            y[i] = mul(y[i], inv);    }}void Convolution(long long A[],long long B[],int n){    for(len=1; len<(n<<1); len<<=1);    for(int i=n; i<len; ++i){        A[i]=B[i]=0;    }    NTT(A,1); NTT(B,1);    for(int i=0; i<len; ++i){        A[i]=mul(A[i],B[i]);    }    NTT(A,-1);}

16.读入外挂

inline int getint(){       int w=0,q=0;       char c=getchar();       while((c<'0' || c>'9') && c!='-') c=getchar();       if (c=='-')  q=1, c=getchar();       while (c>='0' && c<='9') w=w*10+c-'0', c=getchar();       return q ? -w : w;}

我可是有底线的(  ̄▽ ̄)((≧︶≦)


2B桑

0 0