zoukankan      html  css  js  c++  java
  • 2018 Multi-University Training Contest 7

    1001 Age of Moyu (HDU 6386)

     

    思路:

    把Dijkstra的vis数组改成set判一判就好了....

    //By SiriusRen
    #include <bits/stdc++.h>
    using namespace std;
    const int N=800050;
    int n,m,xx,yy,zz,first[N],nxt[N],v[N],w[N],tot,dis[N];
    set<int>vis[N];
    void add(int x,int y,int z){w[tot]=z,v[tot]=y,nxt[tot]=first[x],first[x]=tot++;}
    struct Node{int now,weight,from;}jy;
    bool operator<(Node a,Node b){return a.weight>b.weight;}
    priority_queue<Node>pq;
    void Dijkstra(){
        memset(dis,0x3f,sizeof(dis));dis[1]=0;
        jy.now=1,jy.weight=0,jy.from=-1;
        pq.push(jy);
        while(!pq.empty()){
            Node t=pq.top();pq.pop();
            if(vis[t.now].find(t.from)!=vis[t.now].end())continue;
            vis[t.now].insert(t.from);
            for(int i=first[t.now];~i;i=nxt[i]){
                int W=(w[i]!=t.from);
                if(vis[v[i]].find(w[i])==vis[v[i]].end()&&dis[v[i]]>=t.weight+W){
                    dis[v[i]]=t.weight+W;
                    jy.now=v[i],jy.weight=dis[v[i]];jy.from=w[i];
                    pq.push(jy);
                }
            }
        }
    }
    int main(){
        while(~scanf("%d%d",&n,&m)){
            for(int i=1;i<=n;i++)first[i]=-1;tot=0;
            for(int i=1;i<=n;i++)vis[i].clear();
            for(int i=1;i<=m;i++){
                scanf("%d%d%d",&xx,&yy,&zz);
                add(xx,yy,zz),add(yy,xx,zz);
            }Dijkstra();
            printf("%d
    ",dis[n]>n?-1:dis[n]);
        }
    }

    1005 GuGuFishtion    (HDU 6390)
    定义了一个函数 $G_u(a,b)=$$frac{varphi(ab)}{varphi(a)varphi(b)}$

    让你求$Sigma_{a=1}^{m}Sigma_{b=1}^{n}G_u(a,b) (mod p)$

    我们可以推一发公式

    $G_u(a,b)=frac{varphi(ab)}{varphi(a)varphi(b)}$

    设:

    $varphi(a)=Pi (p_i-1)*P_i ^{a_1}$

    $varphi(b)=Pi (p_i-1)*P_i ^{a_2}$

    则:

    $varphi(ab)=Pi (p_i-1)*p_i^{a_1+a_2-1}$

    $varphi(a)*varphi(b)=Pi (p_i-1)^2*p^{a_1+a_2-2}$

    $frac{varphi(ab)}{varphi(a)varphi(b)}=Pi frac{p_i}{p_i-1}$

    我们发现还是很难搞...

    把式子变一变形

    $frac{varphi(ab)}{varphi(a)varphi(b)}=Pi frac{p_i}{p_i-1}=Pi frac{p_i^{a_i}}{(p_i-1)^{a_i-1}}=frac{gcd(a,b)}{varphi (gcd(a,b))}$

    神奇的事情发生了233333

    再把式子变个形

    $Sigma_{a=1}^mSigma_{b=1}^nfrac{gcd(a,b)}{varphi (gcd(a,b))}$

    $=Sigma_{a=1}^mSigma_{b=1}^nSigma_{k=1}^{min(n,m)}[k==gcd(a,b)]frac{k}{varphi(k)}$

    把k提到前面

    $=Sigma_{k=1}^{min(n,m)}frac{k}{varphi(k)}Sigma_{a=1}^mSigma_{b=1}^n[k==gcd(a,b)]$

    这就好做多了

    可以用mobius反演,容斥也可以

    BZOJ 2005

    //By SiriusRen
    #include <bits/stdc++.h>
    using namespace std;
    #define int long long
    const int N=1000050;
    int phi[N],prime[N],tot,vis[N],cases,m,n,p,inv[N],f[N];
    void init(){
        phi[1]=prime[1]=1;
        for(int i=2;i<N;i++){
            if(!vis[i])phi[i]=i-1,prime[++tot]=i;
            for(int j=1;j<=tot&&i*prime[j]<N;j++){
                vis[i*prime[j]]=1,phi[i*prime[j]]=phi[i]*(prime[j]-1);
                if(i%prime[j]==0){phi[i*prime[j]]=phi[i]*prime[j];break;}
            }
        }
    }
    signed main(){
        scanf("%lld",&cases),init();
        while(cases--){
            scanf("%lld%lld%lld",&m,&n,&p);
            if(n>m)swap(n,m);
            inv[1]=1;
            for(int i=2;i<=n;i++)inv[i]=(p-p/i)*inv[p%i]%p;
            int ans=0;
            for(int i=n;i;i--){
                f[i]=(n/i)*(m/i);
                for(int j=2;i*j<=n;j++)f[i]-=f[i*j];
                ans=(ans+f[i]%p*inv[phi[i]]%p*i)%p;
            }printf("%lld
    ",ans);
        }
    }

    1008 Traffic Network in Numazu  (HDU 6393)

    调到自闭++

    我用的线段树

    //By SiriusRen
    #include <bits/stdc++.h>
    using namespace std;
    #define int long long
    const int N=200050;
    int cases,n,q,op,xx,yy,zz,first[N],nxt[N],v[N],w[N],tot,stk[N],top;
    int incircle[N],revinc[N],cnt,vis[N],tim,in[N],out[N],wei[N],T,rec[N],deep[N];
    int fa[N][20],tmpwei[N],recwei[N],cirwei,tmpid[N],recid[N],revrecid[N],cngwei[N];
    void add(int x,int y,int z){w[tot]=z,v[tot]=y,nxt[tot]=first[x],first[x]=tot++;}
    void dfs(int x){
        stk[++top]=x;vis[x]=1;
        for(int i=first[x];~i;i=nxt[i])if(v[i]!=stk[top-1]){
            tmpwei[top]=w[i],tmpid[top]=i/2+1;
            if(!vis[v[i]])dfs(v[i]);
            else if(!incircle[v[i]]){
                for(int j=top;j;j--){
                    incircle[stk[j]]=++cnt,revinc[cnt]=stk[j];
                    recwei[cnt]=tmpwei[j];cirwei+=recwei[cnt];
                    recid[cnt]=tmpid[j],revrecid[tmpid[j]]=cnt;
                    if(stk[j]==v[i])break;
                }
            }
        }
        top--;
    }
    struct Segtree{
        int tree[N<<3];
        void build(int l,int r,int pos){
            tree[pos]=0;
            if(l==r)return;
            int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1;
            build(l,mid,lson),build(mid+1,r,rson); 
        }
        void insert(int l,int r,int pos,int num,int wei){
            if(l==r){tree[pos]=wei;return;}
            int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1;
            if(mid<num)insert(mid+1,r,rson,num,wei);
            else insert(l,mid,lson,num,wei);
            tree[pos]=tree[lson]+tree[rson];
        }
        int query(int l,int r,int pos,int L,int R){
            if(l>=L&&r<=R)return tree[pos];
            int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1;
            if(mid<L)return query(mid+1,r,rson,L,R);
            else if(mid>=R)return query(l,mid,lson,L,R);
            else return query(l,mid,lson,L,R)+query(mid+1,r,rson,L,R);
        }
    }seg[2];
    void dfs2(int x,int F,int dep){
        deep[x]=dep;
        in[x]=++tim;fa[x][0]=F;if(x!=revinc[T])rec[x]=revinc[T];
        seg[1].insert(1,n*2,1,tim,wei[x]);
        for(int i=first[x];~i;i=nxt[i])if(v[i]!=F&&!incircle[v[i]]){
            cngwei[i/2+1]=v[i];wei[v[i]]=w[i],dfs2(v[i],x,dep+1);
        }out[x]=++tim;
        seg[1].insert(1,n*2,1,tim,-wei[x]);
    }
    int lca(int x,int y){
        if(deep[y]>deep[x])swap(x,y);
        for(int i=19;~i;i--)
            if(deep[fa[x][i]]>=deep[y])x=fa[x][i];
        if(x==y)return x;
        for(int i=19;~i;i--)
            if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
        return fa[x][0];
    }
    signed main(){
        scanf("%lld",&cases);
        while(cases--){
            scanf("%lld%lld",&n,&q);
            for(int i=1;i<=n*2;i++)first[i]=-1,vis[i]=incircle[i]=wei[i]=cngwei[i]=rec[i]=0;
            cnt=tot=tim=cirwei=0;
            for(int i=1;i<=n;i++){
                scanf("%lld%lld%lld",&xx,&yy,&zz);
                add(xx,yy,zz),add(yy,xx,zz);
            }
            dfs(1),seg[0].build(1,cnt,1),seg[1].build(1,n*2,1);
            for(int i=1;i<=cnt;i++)seg[0].insert(1,cnt,1,i,recwei[i]);
            for(T=1;T<=cnt;T++)dfs2(revinc[T],0,1);
            for(int j=1;j<=19;j++)
                for(int i=1;i<=n;i++)
                    fa[i][j]=fa[fa[i][j-1]][j-1];
            for(int i=1;i<=q;i++){
                scanf("%lld%lld%lld",&op,&xx,&yy);
                if(!op){
                    if(cngwei[xx]){
                        seg[1].insert(1,n*2,1,in[cngwei[xx]],yy);
                        seg[1].insert(1,n*2,1,out[cngwei[xx]],-yy);
                    }
                    else{
                        seg[0].insert(1,cnt,1,revrecid[xx],yy);
                        cirwei=cirwei-recwei[revrecid[xx]]+yy;
                        recwei[revrecid[xx]]=yy;
                    }
                }
                else{
                    if(xx==yy){puts("0");continue;}
                    if(rec[xx]==rec[yy]&&rec[xx]){
                        int t=seg[1].query(1,n*2,1,1,in[xx])+seg[1].query(1,n*2,1,1,in[yy]);
                        printf("%lld
    ",t-2*seg[1].query(1,n*2,1,1,in[lca(xx,yy)]));
                    }
                    else if(rec[xx]!=rec[yy]){
                        int t=0;
                        if(rec[xx])t+=seg[1].query(1,n*2,1,1,in[xx]),xx=rec[xx];
                        if(rec[yy])t+=seg[1].query(1,n*2,1,1,in[yy]),yy=rec[yy];
                        int l=incircle[xx],r=incircle[yy];
                        if(l==r)goto ed;
                        if(l>r)swap(l,r);l++;
                        t+=min(seg[0].query(1,cnt,1,l,r),cirwei-seg[0].query(1,cnt,1,l,r));
                        ed:printf("%lld
    ",t);
                    }
                    else{
                        int l=incircle[xx],r=incircle[yy],rem=0;
                        if(l==r)goto ed2;
                        if(l>r)swap(l,r);l++;
                        rem=min(seg[0].query(1,cnt,1,l,r),cirwei-seg[0].query(1,cnt,1,l,r));
                        ed2:printf("%lld
    ",rem);
                    }
                }
            }
        }
    }

    1009 Tree   (HDU 6394)

    (可以用树分块做

    LCT做法和BZOJ 2002差不多

    x和fa^a[x]连边

    改a[x]的时候cnt掉原来的边,倍增找到新点,link上

    询问的时候,把x所在的点makeroot一下,查询size即可。

    //By SiriusRen
    #pragma GCC optimize("O3")
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int N=200050;
    int fa[N],ch[N][2],rev[N],size[N],n,op,q[N],top,a[N],m,xx,yy,F[N][20];
    bool isroot(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
    void push_up(int x){size[x]=size[ch[x][0]]+size[ch[x][1]]+1;}
    void push_down(int x){if(rev[x])rev[ch[x][0]]^=1,rev[ch[x][1]]^=1,rev[x]=0,swap(ch[x][0],ch[x][1]);}
    void rotate(int p){
        int q=fa[p],y=fa[q],x=(ch[q][1]==p);
        ch[q][x]=ch[p][!x],fa[ch[q][x]]=q;
        ch[p][!x]=q,fa[p]=y;
        if(!isroot(q)){
            if(ch[y][0]==q)ch[y][0]=p;
            if(ch[y][1]==q)ch[y][1]=p;
        }fa[q]=p,push_up(q);
    }
    void splay(int x){
        q[++top]=x;
        for(int i=x;!isroot(i);i=fa[i])q[++top]=fa[i];
        while(top)push_down(q[top]),top--;    
        for(int y=fa[x];!isroot(x);rotate(x),y=fa[x])if(!isroot(y)){
            if((ch[fa[y]][0]==y)^(ch[y][0]==x))rotate(x);
            else rotate(y);
        }push_up(x);
    }
    void access(int x){for(int t=0;x;t=x,x=fa[x])splay(x),ch[x][1]=t,push_up(x);}
    void makeroot(int x){access(x),splay(x),rev[x]^=1;}
    void link(int x,int y){makeroot(x),fa[x]=y;}
    void cut(int x,int y){makeroot(x),access(y),splay(y),ch[y][0]=fa[x]=0;}
    void split(int x,int y){makeroot(x),access(y),splay(y);}
    int getlca(int x,int y){
        for(int i=19;~i;i--){
            if(y&(1<<i))x=F[x][i];
        }
        return x;
    }
    int main(){
        int cases;
        scanf("%d",&cases);
        while(cases--){
            memset(fa,0,sizeof(fa));
            memset(rev,0,sizeof(rev));
            memset(size,0,sizeof(size));
            memset(ch,0,sizeof(ch));
            scanf("%d",&n);
            for(int i=2;i<=n;i++)scanf("%d",&F[i][0]);
            for(int j=1;j<=19;j++)
                for(int i=1;i<=n;i++)
                    F[i][j]=F[F[i][j-1]][j-1];
            for(int i=1;i<=n;i++)scanf("%d",&a[i]),link(i+1,getlca(i,a[i])+1);
            scanf("%d",&m);
            while(m--){
                scanf("%d%d",&op,&xx);
                if(op==1)split(1,xx+1),makeroot(xx+1),printf("%d
    ",size[xx+1]-1);
                else scanf("%d",&yy),cut(xx+1,getlca(xx,a[xx])+1),a[xx]=yy,link(xx+1,getlca(xx,a[xx])+1);
            }
            for(int j=1;j<=19;j++)
                for(int i=1;i<=n;i++)
                    F[i][j]=0;
        }
    }

    1010 Sequence   (HDU 6395)

    我们发现$frac{n}{i}$最多有$sqrt n$种取值

    每种取值相同的,我们可以矩阵快速幂加速递推

    就做完了

    调到自闭

    //By SiriusRen
    #include <bits/stdc++.h>
    using namespace std;
    #define int long long
    const int mod=1000000007;
    int cases,A,B,C,D,P,n;
    struct Matrix{
        int a[3][3];
        void init(){memset(a,0,sizeof(a));}
    }cng,fst,lst;
    Matrix operator*(Matrix a,Matrix b){
        Matrix c;c.init();
        for(int i=0;i<3;i++)
            for(int j=0;j<3;j++)
                for(int k=0;k<3;k++)
                    c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j])%mod;
        return c;
    }
    Matrix pow(Matrix a,int x){
        Matrix temp;temp.init();
        for(int i=0;i<3;i++)temp.a[i][i]=1;
        while(x){
            if(x&1)temp=temp*a;
            a=a*a,x>>=1;
        }
        return temp;
    }
    void solve(){
        for(int i=3,last;i<=min(P,n);i=last+1) {
            last=P/(P/i);
            last=min(last,n);
            fst.init();
            fst.a[0][0]=lst.a[0][0],fst.a[1][0]=lst.a[1][0],fst.a[2][0]=P/i;
            Matrix inv=pow(cng,last-i+1);
            lst=inv*fst;
        }
        if(P<n){
            P=max(P,2ll);
            fst.init();
            fst.a[0][0]=lst.a[0][0],fst.a[1][0]=lst.a[1][0];
            Matrix inv=pow(cng,n-P);
            lst=inv*fst;
        }
    }
    signed main(){
        scanf("%lld",&cases);
        while(cases--){
            scanf("%lld%lld%lld%lld%lld%lld",&A,&B,&C,&D,&P,&n);
            cng.init();cng.a[0][1]=1,cng.a[1][0]=C,cng.a[1][1]=D,cng.a[2][2]=1,cng.a[1][2]=1;
            lst.a[0][0]=A,lst.a[1][0]=B,lst.a[2][0]=P;
            solve();
            printf("%lld
    ",lst.a[1][0]);
            
        }
    }

    1011  Swordsman   (HDU 6396)

    //By SiriusRen
    #include <bits/stdc++.h>
    using namespace std;
    const int N=100500;
    int cases,n,k,v[6],cnt[N],Add[6],t[6],ans,addd[6][N];
    struct Node{int wei,add,id;}w[6][N];
    bool operator<(Node a,Node b){return a.wei<b.wei;}
    #define S 100000
    char bf[S],*p1=bf,*p2=bf;
    #define nc() (p1==p2&&(p2=(p1=bf)+fread(bf,1,S,stdin),p2==p1)?-1:*p1++)
    inline int read(){
        int x=0;char ch=nc();for(;ch<'0'||ch>'9';ch=nc());
        for(;ch<='9'&&ch>='0';x=x*10+ch-48,ch=nc());return x;
    }
    int main(){
        cases=read();
        while(cases--){
            memset(cnt,0,sizeof(cnt));ans=0;
            n=read(),k=read();
            for(int i=1;i<=k;i++)v[i]=read(),t[i]=1;
            for(int i=1;i<=n;i++){
                for(int j=1;j<=k;j++)
                    w[j][i].wei=read(),w[j][i].id=i;
                for(int j=1;j<=k;j++)
                    w[j][i].add=read(),addd[j][i]=w[j][i].add;
            }
            for(int i=1;i<=k;i++)sort(w[i]+1,w[i]+1+n);
            while(1){
                for(int i=1;i<=k;i++)Add[i]=0;
                for(int i=1;i<=k;i++){
                    while(w[i][t[i]].wei<=v[i]&&t[i]<=n){
                        cnt[w[i][t[i]].id]++;
                        if(cnt[w[i][t[i]].id]==k){
                            ans++;
                            for(int j=1;j<=k;j++){
                                Add[j]+=addd[j][w[i][t[i]].id];
                            }
                        }
                        t[i]++;
                    }
                }
                for(int i=1;i<=k;i++)v[i]+=Add[i];
                int flg=1;
                for(int i=1;i<=k;i++)if(Add[i])flg=0;
                if(flg)break;
            }
            printf("%d
    ",ans);
            for(int i=1;i<=k;i++){
                printf("%d",v[i]);
                if(i!=k)putchar(' ');
            }puts("");
        }
    }
  • 相关阅读:
    使用VisualVM检测
    《自控力》读书笔记
    【转】Oracle索引的类型
    【转】Oracle索引HINT的使用
    【转】Oracle 执行计划(Explain Plan) 说明
    Oracle分区
    【转】Oracle索引失效问题
    【转】《从入门到精通云服务器》第七讲—负载均衡和CDN技术
    【转】《从入门到精通云服务器》第七讲—IAAS、PAAS、SAAS
    【转】《从入门到精通云服务器》第六讲—OpenStack基础
  • 原文地址:https://www.cnblogs.com/SiriusRen/p/9473294.html
Copyright © 2011-2022 走看看