• 2016-2017 ACM-ICPC Asia-Bangkok Regional Contest


    A. WSI Extreme

    将人按洗澡时间从大到小排序,那么$ans=sum_{i=1}^{n}a_i imeslfloorfrac{i+W-1}{W} floor$。

    当$W$比较大时,暴力枚举每一段,然后求和即可,权值线段树维护。

    当$W$比较小时,线段树上按排名模$W$的值维护$W$个量即可。

    时间复杂度$O(qsqrt{W}log n)$。

    B. Average

    枚举平均数然后容斥+隔板法计算方案数即可。

    #include <bits/stdc++.h>
    using namespace std ;
    
    typedef long long LL ;
    const int mod=1e9+7,Maxn=60*202;
    void up(int &x,int y){x+=y;if(x>=mod)x-=mod;}
    int rev[Maxn],fac[Maxn];
    int C(int x,int y){
    	if(x<y||y<0)return 0;
    	return 1LL*fac[x]*rev[y]%mod*rev[x-y]%mod;
    }
    void solve(){
    	fac[0]=fac[1]=rev[0]=rev[1]=1;
    	for(int i=2;i<Maxn;i++)fac[i]=1LL*fac[i-1]*i%mod;
    	for(int i=2;i<Maxn;i++)rev[i]=1LL*(mod-mod/i)*rev[mod%i]%mod;
    	for(int i=2;i<Maxn;i++)rev[i]=1LL*rev[i-1]*rev[i]%mod;
    }
    int check(int sum,int n,int m){
    	int ret=0;
    	for(int i=0;i<=n;i++){
    		int tmp=1LL*C(n,i)*C(sum+n-i*(m+1)-1,n-1)%mod;
    		//if(i==1)printf("t1=%d t2=%d
    ",C(n,i),C(sum+n-i*(m+1)-1,n-1));
    		if(i&1)tmp=(mod-tmp)%mod;
    		up(ret,tmp);
    		//printf("ret=%d
    ",ret);
    	}
    	return ret;
    }
    int main () {
    	solve();
    	
    		//printf("t2=%d
    ",check(2,2,1));
    	int n,m;
    	while(scanf("%d%d",&n,&m)!=EOF){
    		if(!n&&!m)break;
    		int ans=0;
    		for(int i=0;i<=m;i++){
    			up(ans,1LL*check((n-1)*i,n-1,m)%mod);
    		}
    		//printf("t1=%d
    ",check(0,2,1));
    		
    		//printf("t2=%d
    ",check(2,2,1));
    		ans=1LL*ans*n%mod;
    		printf("%d
    ",ans);
    	}
    	return 0 ;
    }
    

      

    C. Big Bang

    $ans=sum_{i=1}^nmu(i)lfloorfrac{n}{i} floor^4$。

    D. Find C

    首先通过exgcd求出一组解,然后往两侧延伸$K$个即可。

    #include <bits/stdc++.h>
    using namespace std ;
    
    typedef long long LL ;
    const LL LIM=100000000000000LL;
    typedef pair<LL,LL>pi;
    LL sx,sy,ex,ey;
    int K;
    LL gcd(LL x,LL y){
    	if(!x)return y;
    	if(!y)return x;
    	return __gcd(x,y);
    }
    inline LL exgcd(LL a,LL b,LL &x,LL &y){
    	if(!b)return x=1,y=0,a;
    	LL d=exgcd(b,a%b,y,x);
    	y-=a/b*x;
    	return d;
    }
    int ok(LL x,LL y){
    	if(abs(x)>LIM||abs(y)>LIM)return 0;
    	return 1;
    }
    bool check(LL x,LL y){
    	if(x==sx&&y==sy)return 0;
    	if(x==ex&&y==ey)return 0;
    	if(__gcd(abs(x-sx),abs(y-sy))>1)return 0;
    	if(__gcd(abs(x-ex),abs(y-ey))>1)return 0;
    	return 1;
    }
    /*
    void getst(LL &x,LL &y,LL stepx,LL stepy){
    	if(!stepx){
    		if(stepy<0){
    			y%=-stepy;
    		}
    		else {
    			y%=stepy;
    		}
    	}
    	else
    	if(!stepy){
    		x%=stepx;
    	}
    	else{
    		if(stepy>0){
    			LL 
    		}
    	}
    }
    */
    set<pi>res;
    void solve(LL S){
    	LL A=abs(sy-ey),B=abs(sx-ex);
    	LL gc=gcd(A,B);
    	LL tA=(sy-ey)/gc,tB=(ex-sx)/gc;
    	LL ftA=abs(tA),ftB=abs(tB);
    	LL C=S-(sx*ey-ex*sy);
    	C/=gc;
    	LL x,y;
    	exgcd(ftA,ftB,x,y);
    	if(ftB){
    		x=x*(C%ftB)%ftB;
    		y=(C-x*ftA)/ftB;
    	}
    	else{
    		y=y*(C%ftA)%ftA;
    		x=(C-y*ftB)/ftA;
    	}
    	if(tA<0)x=-x;
    	if(tB<0)y=-y;
    	LL stepx=(ex-sx)/gc,stepy=(ey-sy)/gc;
    	//if(!ok(x,y))while(1);
    	for(LL curx=x+stepx,cury=y+stepy;res.size()<K&&ok(curx,cury);curx+=stepx,cury+=stepy){
    		if(check(curx,cury)){
    			//printf("curx=%lld cury=%lld
    ",curx,cury);
    			res.insert(pi(curx,cury));
    		}
    	}
    	
    	for(LL curx=x,cury=y;res.size()<K&&ok(curx,cury);curx-=stepx,cury-=stepy){
    		if(check(curx,cury)){
    			res.insert(pi(curx,cury));
    		}
    	}
    }
    int main () {
    	int _;scanf("%d",&_);
    	while(_--){
    		scanf("%lld%lld%lld%lld%d",&sx,&sy,&ex,&ey,&K);
    		if(ex<sx){swap(sx,ex);swap(sy,ey);}
    		res.clear();
    		LL S=__gcd(abs(sx-ex),abs(sy-ey));
    		solve(S);
    		solve(-S);
    		if(res.size()<K)while(1);
    		for(set<pi>::iterator it=res.begin();it!=res.end();it++){
    			printf("%lld %lld
    ",it->first,it->second);
    		}
    	}
    	return 0 ;
    }
    

      

    E. ACM Tax

    可持久化线段树维护即可。

    #include<cstdio>
    #include<algorithm>
    #include<cstdlib>
    #include<cstring>
    using namespace std;
    typedef long long ll;
    const int N=50010,M=N*20;
    int T,C;
    int n,m,i,x,y,z,g[N],v[N<<1],w[N<<1],nxt[N<<1],ed;
    int f[N],d[N],size[N],son[N],top[N];
    int tot,rt[N],l[M],r[M],val[M];
    inline void add(int x,int y,int z){v[++ed]=y;w[ed]=z;nxt[ed]=g[x];g[x]=ed;}
    int ins(int x,int a,int b,int c){
      int y=++tot;
      val[y]=val[x]+1;
      if(a==b)return y;
      int mid=(a+b)>>1;
      if(c<=mid){
        l[y]=ins(l[x],a,mid,c);
        r[y]=r[x];
      }else{
        l[y]=l[x];
        r[y]=ins(r[x],mid+1,b,c);
      }
      return y;
    }
    void dfs(int x){
      size[x]=1;
      for(int i=g[x];i;i=nxt[i])if(v[i]!=f[x]){
        f[v[i]]=x,d[v[i]]=d[x]+1;
        rt[v[i]]=ins(rt[x],1,100000,w[i]);
        dfs(v[i]),size[x]+=size[v[i]];
        if(size[v[i]]>size[son[x]])son[x]=v[i];
      }
    }
    void dfs2(int x,int y){
      top[x]=y;
      if(son[x])dfs2(son[x],y);
      for(int i=g[x];i;i=nxt[i])if(v[i]!=son[x]&&v[i]!=f[x])dfs2(v[i],v[i]);
    }
    inline int lca(int x,int y){
      for(;top[x]!=top[y];x=f[top[x]])if(d[top[x]]<d[top[y]])swap(x,y);
      return d[x]<d[y]?x:y;
    }
    inline int kth(int x,int y,int z,int k){
      int a=1,b=100000,mid,t;
      while(a<b){
        mid=(a+b)>>1;
        t=val[l[x]]+val[l[y]]-2*val[l[z]];
        if(k<=t){
          b=mid;
          x=l[x];
          y=l[y];
          z=l[z];
        }else{
          k-=t;
          a=mid+1;
          x=r[x];
          y=r[y];
          z=r[z];
        }
      }
      return a;
    }
    inline int query(int x,int y){
      int z=lca(x,y);
      int all=d[x]+d[y]-d[z]*2;
      if(all&1)return kth(rt[x],rt[y],rt[z],(all+1)/2)*2;
      return kth(rt[x],rt[y],rt[z],all/2)+kth(rt[x],rt[y],rt[z],all/2+1);
    }
    int main(){
      scanf("%d",&T);
      for(C=1;C<=T;C++){
        scanf("%d",&n);
        ed=0;
        for(i=1;i<=n;i++)g[i]=f[i]=d[i]=size[i]=son[i]=top[i]=rt[i]=0;
        for(i=1;i<n;i++)scanf("%d%d%d",&x,&y,&z),add(x,y,z),add(y,x,z);
        dfs(1);
        dfs2(1,1);
        scanf("%d",&m);
        while(m--)scanf("%d%d",&x,&y),printf("%.1f
    ",0.5*query(x,y));
        for(i=1;i<=tot;i++)l[i]=r[i]=val[i]=0;
        tot=0;
      }
    }
    

      

    F. Dictionary Game

    建出Trie树,然后就是经典树上删边游戏。

    #include<cstdio>
    #include<algorithm>
    #include<cstdlib>
    #include<cstring>
    using namespace std;
    typedef long long ll;
    const int N=100010*40;
    int T,C,tot,son[N][26],sg[N],f[N];
    int n,i,j;
    inline int ins(){
      static char s[99];
      scanf("%s",s);
      int l=strlen(s);
      int x=0;
      for(int i=0;i<l;i++){
        int w=s[i]-'a';
        if(!son[x][w]){
          son[x][w]=++tot;
          f[tot]=x;
        }
        x=son[x][w];
      }
      return x;
    }
    inline void cal(int x){
      sg[x]=0;
      for(int i=0;i<26;i++)if(son[x][i])sg[x]^=sg[son[x][i]]+1;
    }
    void dfs(int x){
      for(int i=0;i<26;i++)if(son[x][i])dfs(son[x][i]);
      cal(x);
    }
    inline void up(int x){
      while(x){
        cal(x);
        x=f[x];
      }
      cal(0);
    }
    int main(){
      scanf("%d",&T);
      for(C=1;C<=T;C++){
        printf("Case %d:
    ",C);
        scanf("%d",&n);
        while(n--)ins();
        dfs(0);
        scanf("%d",&n);
        while(n--){
          up(ins());
          puts(sg[0]?"1":"2");
        }
        for(i=0;i<=tot;i++)for(j=f[i]=sg[i]=0;j<26;j++)son[i][j]=0;
        tot=0;
      }
    }
    

      

    G. Binary Strings

    矩阵快速幂优化DP转移。

    #include <bits/stdc++.h>
    using namespace std ;
    
    typedef long long LL ;
    const int mod=1e9+7;
    void up(int &x,int y){x+=y;if(x>=mod)x-=mod;}
    struct Mat{
    	int a[3][3];
    	Mat operator *(const Mat&x)const{
    		Mat ret;
    		for(int i=0;i<3;i++){
    			for(int j=0;j<3;j++){
    				int t=0;
    				for(int k=0;k<3;k++){
    					up(t,1LL*a[i][k]*x.a[k][j]%mod);
    				}
    				ret.a[i][j]=t;
    			}
    		}
    		return ret;
    	}
    	void init(int t){
    		for(int i=0;i<3;i++){
    			for(int j=0;j<3;j++){
    				a[i][j]=i==j?t:0;
    			}
    		}
    	}
    }ori;
    Mat powmod(Mat x,LL y){
    	Mat ret;
    	ret.init(1);
    	while(y){
    		if(y&1){ret=ret*x;}
    		y>>=1;
    		x=x*x;
    	}
    	return ret;
    }
    int go(LL x){
    	Mat tmp=powmod(ori,x+1);
    	return tmp.a[0][2];
    }
    void solve(){
    	LL l,r,k;
    	scanf("%lld%lld%lld",&l,&r,&k);
    	ori.init(0);
    	ori.a[0][0]=1;
    	ori.a[0][1]=1;
    	ori.a[1][0]=1;
    	ori=powmod(ori,k);
    	ori.a[0][2]=1;
    	ori.a[1][2]=1;
    	ori.a[2][2]=1;
    	ori.a[2][0]=ori.a[2][1]=0;
    	int ans=go(r/k);
    	ans-=go((l-1)/k);
    	if(ans<0)ans+=mod;
    	printf("%d
    ",ans);
    }
    int main () {
    	int _,cas=1;scanf("%d",&_);
    	while(_--){
    		printf("Case %d: ",cas++);
    		solve();
    	}
    	return 0 ;
    }
    

      

    H. Witcher Potion

    $f[S][i][j][k]$表示已经使用过的药水集合为$S$,当前能量为$i$,毒性为$j$,上一次是否嗑药为$k$时最多能打多少只怪物,然后DP即可。

    #include<cstdio>
    #include<algorithm>
    #include<cstdlib>
    #include<cstring>
    using namespace std;
    typedef long long ll;
    const int inf=10000000;
    int T,K,M,n,i,j,k,ans,t,e[11],p[11],f[1<<8][111][111][2],o;
    inline void up(int&x,int y){if(x<y)x=y;}
    int main(){
      scanf("%d",&T);
      while(T--){
        scanf("%d%d%d",&K,&M,&n);
        for(i=0;i<n;i++)scanf("%d",&e[i]);
        for(i=0;i<n;i++)scanf("%d",&p[i]);
        for(i=0;i<1<<n;i++)for(j=1;j<=100;j++)for(k=0;k<100;k++)f[i][j][k][0]=f[i][j][k][1]=-inf;
        up(f[0][100][0][0],0);
        for(i=0;i<1<<n;i++)for(j=100;j;j--)for(k=99;~k;k--)for(o=0;o<2;o++)if(f[i][j][k][o]>=0){
          //kill a monster
          if(j>K)up(f[i][j-K][max(0,k-M)][0],f[i][j][k][o]+1);
          //drink
          if(!o)for(t=0;t<n;t++)if(!(i>>t&1)){
            if(k+p[t]<100)up(f[i|(1<<t)][min(100,j+e[t])][k+p[t]][1],f[i][j][k][o]);
          }
    
        }
        ans=0;
        for(i=0;i<1<<n;i++)for(j=1;j<=100;j++)for(k=0;k<100;k++){
          up(ans,f[i][j][k][0]);
          up(ans,f[i][j][k][1]);
        }
        printf("%d
    ",ans);
      }
    }
    

      

    I. Sky Tax

    根据根与询问点的位置关系分类讨论即可。

    #include<cstdio>
    #include<algorithm>
    #include<cstdlib>
    using namespace std;
    typedef long long ll;
    const int N=1000010,M=2000010;
    int T,C,n,m,root,x,y,i,g[N],v[N<<1],nxt[N<<1],ed;
    int st[N],en[N],size[N],dfn;
    int son[N],top[N],d[N],f[N];
    inline void add(int x,int y){
      v[++ed]=y;nxt[ed]=g[x];g[x]=ed;
    }
    void dfs(int x){
      size[x]=1;
      for(int i=g[x];i;i=nxt[i])if(v[i]!=f[x]){
        f[v[i]]=x,d[v[i]]=d[x]+1;
        dfs(v[i]);
        size[x]+=size[v[i]];
        if(size[v[i]]>size[son[x]])son[x]=v[i];
      }
    }
    void dfs2(int x,int y){
      st[x]=++dfn;top[x]=y;
      if(son[x])dfs2(son[x],y);
      for(int i=g[x];i;i=nxt[i])if(v[i]!=son[x]&&v[i]!=f[x])dfs2(v[i],v[i]);
      en[x]=dfn;
    }
    inline int lca2(int x,int y){
      int t;
      while(top[x]!=top[y])t=top[y],y=f[top[y]];
      return x==y?t:son[x];
    }
    inline int ask(int x){
      if(root==x)return n;
      if(st[x]>st[root]||en[x]<en[root])return size[x];
      return n-size[lca2(x,root)];
    }
    void check(int x){
      if(x<1||x>n)exit(0);
    }
    int main(){
      scanf("%d",&T);
      for(C=1;C<=T;C++){
        printf("Case #%d:
    ",C);
        scanf("%d%d%d",&n,&m,&root);
        check(root);
        for(ed=dfn=0,i=1;i<=n;i++)g[i]=0;
        for(i=1;i<=n;i++)size[i]=son[i]=top[i]=f[i]=d[i]=0;
        for(i=1;i<n;i++){
          //x=i+1;y=rand()%i
          scanf("%d%d",&x,&y);
          check(x);
          check(y);
          add(x,y),add(y,x);
        }
        dfs(1);
        dfs2(1,1);
        while(m--){
          scanf("%d%d",&x,&y);
          check(y);
          if(x==0)root=y;
          else{
            printf("%d
    ",ask(y));
          }
        }
      }
    }
    

      

    J. Printing Press

    留坑。

    K. Expected Number of Connected Components

    留坑。

    L. Coordinates

    建树DFS即可确定出每个点的坐标。

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N=100010,M=2000010;
    const ll inf=1LL<<60;
    int n,m,i,f[N],g[N],v[M],wx[M],wy[M],nxt[M],ed;
    ll minx,miny,basex[N],basey[N],xx[N],yy[N];
    inline void add(int x,int y,int dx,int dy){
      v[++ed]=y;
      wx[ed]=dx;
      wy[ed]=dy;
      nxt[ed]=g[x];
      g[x]=ed;
    }
    void dfs(int x,int y,ll X,ll Y){
      if(f[x])return;
      f[x]=y;
      xx[x]=X;
      yy[x]=Y;
      minx=min(minx,X);
      miny=min(miny,Y);
      for(int i=g[x];i;i=nxt[i])dfs(v[i],y,X+wx[i],Y+wy[i]);
    }
    int main(){
      scanf("%d%d",&n,&m);
      while(m--){
        int x,y,dx,dy;
        scanf("%d%d%d%d",&x,&y,&dx,&dy);
        add(x,y,dx,dy);
        add(y,x,-dx,-dy);
      }
      for(i=1;i<=n;i++)if(!f[i]){
        minx=inf;
        miny=inf;
        dfs(i,i,0,0);
        basex[i]=-minx;
        basey[i]=-miny;
      }
      for(i=1;i<=n;i++)printf("%I64d %I64d
    ",xx[i]+basex[f[i]],yy[i]+basey[f[i]]);
    }
    

    总结:

    • I题发现模板有误。
  • 相关阅读:
    在springboot程序中自定义注解和反序列化实现
    文章相似度算法调研
    HTTP协议详解
    prototype.js 让你更深入的了解javascript的面向对象特性(转)
    ajax框架汇总
    prototype源码分析(转)
    c#中静态成员和实例成员(转)
    .NET中IDisposable接口的基本使用 (转)
    sql server 数据库优化(转)
    ADO.NET事物
  • 原文地址:https://www.cnblogs.com/clrs97/p/6132080.html
Copyright © 2020-2023  润新知