2021-03-06周总结

开学前和这周主要练习了图论树论,还刷了一些atcoder上的题。新学了中国剩余定理,虚树。与树论有关的基本都是树上的dp,练了换根dp,dfn序,lca,关于树论还有几个比较难的算法(树分治,树分块,仙人掌,LCT,区间图等。。)这些我目前还没有接触到。另外刷atcoder练习了一些dp。

中国剩余定理的模板

int exgcd(int a,int b,int &x,int &y){
    int d = a;
    if(b){ d = exgcd(b, a%b, y, x);y -= (a/b)*x;}
    else{x = 1;y = 0;}
    return d;
}
int inv(int a,int mo){
    int x,y;
    int d = exgcd(a,n,x,y);
    return d == 1 ? (x + mo)%mo : -1;//-1表示不存在,并对逆元调整
}
int gcd(int a,int b){
    return b?gcd(b,a%b):a;
}
int CRT(int n,int a[],int mo[]){//互质的时候
    int mM = 1,W,x,y,res = 0;
    for(int i = 1;i<=n;i++) mM *= mo[i];
    for(int i = 1;i<=n;i++){
        W = mM/mo[i];
        exgcd(W,mo[i],x,y);
        res = (res + x*W%mM*a[i])%mM;
    }
    return (res + mM)%mM;
}
bool merge(int a1,int m1,int a2,int m2,int &A,int &mo){
    int c = (a2 - a1),d = gcd(m1,m2);
    if(c % d) return 0;//gcd(m1,m2)|(a2 - a1)时才有解
    c = (c%m2 + m2)%m2;//将c变为[0,m2)之间的数
    c /= d;m1 /= d;m2 /= d;//两边除以d
    c = c*inv(m1,m2) % m2;//将m1/d 移到右边
    mo = m1*m2*d;// mo = m1 * m2 /d
    A = (c*m1%mo*d%mo + a1)%mo;
    return 1;
}
int EXCRT(int n,int a[],int mo[]){
    int a1 = a[1],m1 = mo[1],A,Mo;
    for(int i = 2;i<=n;i++){
        if(!merge(a1,m1,a[i],mo[i],A,Mo)) return -1;//不合法
        a1 = A;m1 = Mo;
    }
    return (a1 + m1)%m1;
}

虚树模板

int stk[N],top;//用一个栈记录虚树的一条树链
vector<int> G[N];//记录虚树
void build_tree(vector<int> &a){
    sort(a.begin(),a.end(),[](int x,int y){
        return dfn[x] < dfn[y];//对dfn进行排序从小的开始扫描
    });
    top = 0;
    if(a[0] != 1) stk[top = 1] = 1;//先让根1入栈
    for(int x : a){
        int p = lca(stk[top],x);
        if(p == stk[top]) {stk[++top] = x;continue;}//说明这个点在链上,入栈
        while(top > 1 && dep[stk[top-1]] >= dep[p]){ //lca 不在栈里
            G[stk[top-1]].push_back(stk[top]);		 // top-1 不在 top-2...也可能不在
            top--;
        }
        if(stk[top] != p) { //新加的点和原来在栈里的点不在一条链上
            G[p].push_back(stk[top]);
            stk[top] = p;
        }
        stk[++top] = x;
    }
    while(top > 1) { //把栈里剩下的点连上
        G[stk[top-1]].push_back(stk[top]);
        top--;
    }
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值