zoukankan      html  css  js  c++  java
  • 2017"百度之星"程序设计大赛

    这套题体验极差。

    PROBLEM 1001 - 小C的倍数问题

      OvO http://acm.hdu.edu.cn/showproblem.php?pid=6108

      (2017"百度之星"程序设计大赛 - 初赛(A) - 1001)

       10进制下,各位数和是9的倍数的数能被9整除是因为 10^k-1=能被9整除

       实质上就是10-1的因数有9

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    
    using namespace std;
    
    int calcu(int spl)
    {
    	int i,j,ret=0;
    	for(i=1;i*i<=spl;i++)
    		if(spl%i==0)
    		{
    			ret++;
    			if(i*i!=spl)
    				ret++;
    		}
    	return ret;
    }
    
    int main()
    {
    	int cas;
    	int p;
    	cin>>cas;
    	while(cas--)
    	{
    		cin>>p;
    		cout<<calcu(p-1)<<endl;
    	}
    	return 0;
    }
    

      

     

    PROBLEM 1002 - 数据分割

      OvO http://acm.hdu.edu.cn/showproblem.php?pid=6109

      (2017"百度之星"程序设计大赛 - 初赛(A) - 1002)

      每次拿到题目给的2个点,如果这两个点是相等的,则把这两个点所在的并查集合并,否则,找到这两个点的根,然后把把这两个根节点连一条边。

      每次合并并查集的时候,要把相连的边也转移(选择边少的那个并查集转移)。

      每次读入2个点,记录这两个点的具体值,存到栈里,以后每次清空,清空栈里这些值对应的位置即可,这样就算要清空L次也不会超时。

      (思路来源于瞟了一眼某个我忘了在哪里的地方)

      

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    #include <queue>
    
    using namespace std;
    
    const int N=2e5+44;
    
    struct node{
        int u,v;
        int next;
    }edge[2*N];
    
    struct clearpair
    {
    	int a,b;
    } ;
    
    queue<clearpair> clearlist;
    int cnt,num;
    int head[N];
    int answer[N],lanswer;
    int fa[N],tol[N],hav[N];
    int t;
    
    void addedge(int u,int v)
    {
        edge[num].u=u;
        edge[num].v=v;
        edge[num].next=head[u];
        head[u]=num++;
    }
    
    void changeedge(int id,int u)
    {
    	edge[id].u=u;
    	edge[id].next=head[u];
    	head[u]=id;
    }
    
    void init(int sz=100000)
    {
    	t=0;
    	num=0;
       	for(int i=1;i<=sz;i++)
    	{
    		head[i]=-1; 
    		fa[i]=i;
    		tol[i]=1;
    	}
    	while(!clearlist.empty())
    		clearlist.pop();
    }
    
    void clear()
    {
    	clearpair tmp;
    	int a,b;
    	t=0; num=0;
    	while(!clearlist.empty())
    	{
    		tmp=clearlist.front();
    		clearlist.pop();
    		head[tmp.a]=-1; fa[tmp.a]=tmp.a; tol[tmp.a]=1;
    		head[tmp.b]=-1; fa[tmp.b]=tmp.b; tol[tmp.b]=1;		
    	}
    }
    
    int fff(int x)
    {
    	if(fa[x]==x)
    		return x;
    	fa[x]=fff(fa[x]);
    	return fa[x];
    }
    
    bool merge(int a,int b)
    {
    	int v,nxttmp,i,j,pa,pb,pv;
    	pa=fff(a); pb=fff(b);
    	if(pa==pb) return true;
    	if(hav[pa]>hav[pb])
    		swap(pa,pb),swap(a,b);
    	hav[pb]+=hav[pa];
    	fa[pa]=pb;
    	for(i=head[pa],nxttmp=edge[i].next;i!=-1;i=nxttmp,nxttmp=edge[i].next)
    	{
    		v=edge[i].v; pv=fff(v);
    		if(pv==pb)
    			return false;
    		changeedge(i,pb);
    	}
    	return true;
    }
    
    bool solve(int a,int b,int c)
    {
    	int pa,pb;
    	if(c==0)
    	{
    		pa=fff(a); pb=fff(b);
    		if(pa==pb) return false;
    		addedge(pa,pb);
    		addedge(pb,pa);
    		return true;
    	}
    	else
    		return merge(a,b);
    }
    
    int main()
    {
    	int i,j,a,b,c;
    	int T;
    	scanf("%d",&T);
    	lanswer=0;
    	init();
    	while(T--)
    	{
    		t++;
    		scanf("%d%d%d",&a,&b,&c);
    		clearlist.push((clearpair){a,b});
    		if(solve(a,b,c)==false)
    		{
    			answer[++lanswer]=t;
    			clear();
    		}
    	}
    	printf("%d
    ",lanswer);
    	for(i=1;i<=lanswer;i++)
    		printf("%d
    ",answer[i]);
    	return 0;
    }
    

      

      

    PROBLEM 1003 - 路径交

      Q∧Q http://acm.hdu.edu.cn/showproblem.php?pid=6110

      (2017"百度之星"程序设计大赛 - 初赛(A) - 1003)

      其实题目求的是[L,R]这个区间的路径的交,(而不是L,R两条的路径交),而且路径交的定义是[L,R]都覆盖的路径,(而不是只要有2条路径覆盖就行),

      开个线段树,线段树中区间[li,ri]对应li~ri这些路径的交。

      求路径交用LCA

      (题意和思路来源于某大佬

    #include <iostream>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <cstdio>
    
    using namespace std;
    
    typedef long long ll;
    
    const int MAXN=500044;
    
    int rmq[2*MAXN];//建立RMQ的数组
    
    struct ST
    {
        int mm[2*MAXN];//mm[i]表示i的最高位,mm[1]=0,mm[2]=1,mm[3]=1,mm[4]=2
        int dp[MAXN*2][35];
        void init(int n)
        {
            mm[0]=-1;
            for(int i=1;i<=n;i++)
            {
                mm[i]=((i&(i-1))==0?mm[i-1]+1:mm[i-1]);
                dp[i][0]=i;
            }
            for(int j=1;j<=mm[n];j++)
              for(int i=1;i+(1<<j)-1<=n;i++)
                 dp[i][j]=rmq[dp[i][j-1]]<rmq[dp[i+(1<<(j-1))][j-1]]?dp[i][j-1]:dp[i+(1<<(j-1))][j-1];
        }
        int query(int a,int b)//查询a到b间最小值的下标
        {
            if(a>b)swap(a,b);
            int k=mm[b-a+1];
            return rmq[dp[a][k]]<rmq[dp[b-(1<<k)+1][k]]?dp[a][k]:dp[b-(1<<k)+1][k];
        }
    };
    
    struct Node
    {
        int to,next,val;
    };
    
    struct LCA2RMQ
    {
        int n;//结点个数
        Node edge[2*MAXN];//树的边,因为是建无向边,所以是两倍
        int tol;//边的计数
        int head[MAXN];//头结点
    
        bool vis[MAXN];//访问标记
        int F[2*MAXN];//F是欧拉序列,就是DFS遍历的顺序
        int P[MAXN];//某点在F中第一次出现的位置
        int cnt;
    
        ST st;
        void init(int n)//n为所以点的总个数,可以从0开始,也可以从1开始
        {
            this->n=n;
            tol=0;
            memset(head,-1,sizeof(head));
        }
        void addedge(int a,int b,int val)//加边
        {
            edge[tol].to=b;
            edge[tol].next=head[a];
            edge[tol].val=val;
            head[a]=tol++;
            edge[tol].to=a;
            edge[tol].next=head[b];
            edge[tol].val=val;
            head[b]=tol++;
        }
    
        int query(int a,int b)//传入两个节点,返回他们的LCA编号
        {
            return F[st.query(P[a],P[b])];
        }
    
        void dfs(int a,int lev)
        {
            vis[a]=true;
            ++cnt;//先加,保证F序列和rmq序列从1开始
            F[cnt]=a;//欧拉序列,编号从1开始,共2*n-1个元素
            rmq[cnt]=lev;//rmq数组是深度序列
            P[a]=cnt;
            for(int i=head[a];i!=-1;i=edge[i].next)
            {
                int v=edge[i].to;
                if(vis[v])continue;
                dfs(v,lev+1);
                ++cnt;
                F[cnt]=a;
                rmq[cnt]=lev;
            }
        }
    
        void solve(int root)
        {
            memset(vis,false,sizeof(vis));
            cnt=0;
            dfs(root,0);
            st.init(2*n-1);
        }
    }lca;
    
    struct Line
    {
    	int a,b,flag;
    } line[MAXN],answer[MAXN],tree[MAXN*3];
    
    ll dep[MAXN];
    int lv[MAXN];
    
    bool cmp(int x,int y)
    {
    	return lv[x]>lv[y];
    }
    
    Line merge(Line x,Line y)
    {
    	Line ret; ret.flag=true;
    	if(x.flag==false || y.flag==false)
    	{
    		ret.flag=false;
    		return ret;
    	}
    	int lcax=lca.query(x.a,x.b),lcay=lca.query(y.a,y.b);
    	if(lv[lcax]>lv[lcay])
    		swap(x,y),swap(lcax,lcay);
    	int lca11=lca.query(x.a,y.a),lca12=lca.query(x.a,y.b),lca21=lca.query(x.b,y.a),lca22=lca.query(x.b,y.b);
    	int que[5];
    	que[1]=lca11; que[2]=lca12; que[3]=lca21; que[4]=lca22;
    	sort(que+1,que+4+1,cmp);
    	ret.a=que[1]; ret.b=que[2];
    //	cout<<que[1]<<'-'<<que[2]<<endl;
    	if(lv[ret.a]<lv[lcax] || lv[ret.b]<lv[lcax] || lv[ret.a]<lv[lcay] || lv[ret.b]<lv[lcay]) ret.flag=false;
    //	cout<<ret.a<<' '<<ret.b<<' '<<lcax<<' '<<lcay<<' '<<ret.flag<<endl;
    	return ret;
    }
    
    void build(int rt,int li,int ri)
    {
    	if(li==ri)
    	{
    		tree[rt]=line[ri];
    		return ;
    	}
    	int mid=(li+ri)>>1,lc=(rt<<1),rc=(rt<<1)+1;
    	build(lc,li,mid);
    	build(rc,mid+1,ri);
    	tree[rt]=merge(tree[lc],tree[rc]);
    }
    
    Line query(int rt,int li,int ri,int lq,int rq)	//get Line
    {
    	bool flag=false;
    	Line ret;
    	if(lq<=li && ri<=rq)
    		return tree[rt];
    	int mid=(li+ri)>>1,lc=(rt<<1),rc=(rt<<1)+1;
    	if(mid>=lq)
    	{
    		flag=true;
    		ret=query(lc,li,mid,lq,rq);
    	}
    	if(mid+1<=rq)
    	{
    		if(flag==false)
    			ret=query(rc,mid+1,ri,lq,rq);
    		else
    			ret=merge(ret,query(rc,mid+1,ri,lq,rq));
    	}
    	return ret;
    }
    
    void getdepth(int rt,int pa,ll depnow,int lvnow)
    {
    	int i,j,v;
    	lv[rt]=lvnow;
    	dep[rt]=depnow;
    	for(i=lca.head[rt];i!=-1;i=lca.edge[i].next)
    	{
    		v=lca.edge[i].to;
    		if(v==pa) continue;
    		getdepth(v,rt,depnow+lca.edge[i].val,lvnow+1);
    	}
    }
    
    ll getlength(int a,int b)
    {
    	int c=lca.query(a,b);
    	return dep[a]-dep[c]+dep[b]-dep[c];
    }
    
    inline void read(int &ret)
    {
        int k=0;
        char f=1;
        char c=getchar();
        for(;!isdigit(c);c=getchar() )
            if(c=='-')
                f=-1;
        for(;isdigit(c);c=getchar() )
            k=k*10+c-'0';
        ret=k*f;
    }
    
    int main()
    {
    	int i,j,a,b,c,n,m,q;
    	ll ans;
    	while(scanf("%d",&n)!=EOF)
    	{
    		lca.init(n);
    		for(i=1;i<n;i++)
    		{
    			read(a); read(b); read(c);
    			lca.addedge(a,b,c);
    		}
    		lca.solve(1);
    		getdepth(1,-1,0,0);
    		read(m);
    		for(i=1;i<=m;i++)
    		{
    			read(line[i].a); read(line[i].b);
    			line[i].flag=true;
    		}
    		build(1,1,m);
    		read(q);
    		for(i=1;i<=q;i++)
    		{
    			read(a); read(b);
    			answer[i]=query(1,1,m,a,b);
    		}
    		for(i=1;i<=q;i++)
    		{
    	//		cout<<answer[i].a<<' '<<answer[i].b<<endl;
    			if(answer[i].flag)
    				ans=getlength(answer[i].a,answer[i].b);
    			else
    				ans=0;
    			printf("%lld
    ",ans);
    		}
    	}
    	return 0;
    }
    
    /*
    
    4
    1 2 2000000000
    2 3 2000000000
    1 4 2000000000
    4
    3 4
    3 4
    1 4
    2 3
    4
    1 2
    3 4
    1 3
    1 4
    
    */ 
    

      

     

    PROBLEM 1005 - 小今夕何夕

      OvO http://acm.hdu.edu.cn/showproblem.php?pid=6112

      (2017"百度之星"程序设计大赛 - 初赛(A) - 1005)

       注意2-29

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    
    using namespace std;
    
    int a,b,c;
    int id;	
    int inc[3]={1,2};
    
    int jg(int spl)
    {
    	if(spl%400==0)
    		return 1;
    	if(spl%100==0)
    		return 0;
    	if(spl%4==0)
    		return 1;
    	return 0;
    }
    
    int solve()
    {
    	int ret=a+1,i,j,now=0;
    	if(b==2 && c==29)
    	{
    		id=a+1;
    		for(i=id;;i++,ret++)
    		{
    			now+=inc[jg(i)];
    			now%=7;
    			if(jg(i) && now==0)
    				return ret;
    		}
    	}
    	id=a;
    	if(b>2) id++;
    	for(i=id;;i++,ret++)
    	{
    		now+=inc[jg(i)];
    		now%=7;
    //		cout<<"ret: "<<ret<<' '<<"i: "<<i<<' '<<"now: "<<now<<endl;
    		if(now==0)
    			return ret;
    	}
    }
    
    int main()
    {
    	int i,j;
    	int T;
    	cin>>T;
    	while(T--)
    	{
    		scanf("%d-%d-%d",&a,&b,&c);
    		printf("%d
    ",solve());
    	}
    	return 0;
    }
    

      

     

    PROBLEM 1006 - 度度熊的01世界

      OvO http://acm.hdu.edu.cn/showproblem.php?pid=6113

      (2017"百度之星"程序设计大赛 - 初赛(A) - 1006)

       分步慢慢来

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <cstring>
    
    using namespace std;
    
    int n,m;
    char mp[111][111];
    int tag1[111][111],tag0[111][111];
    int dx[5]={0,0,1,-1};
    int dy[5]={1,-1,0,0};
    
    bool check(int x,int y)
    {
    	if(x<=0 || x>n || y<=0 || y>m)
    		return false;
    	return true;
    }
    
    void dfs1(int x,int y)
    {
    	int i,j,xx,yy;
    	tag1[x][y]=1;
    	for(i=0;i<4;i++)
    	{
    		xx=x+dx[i];
    		yy=y+dy[i];
    		if(check(xx,yy) && tag1[xx][yy]==0 && mp[xx][yy]=='1')
    			dfs1(xx,yy);
    	}
    }
    
    bool gettag1()
    {
    	int i,j;
    	for(i=1;i<=n;i++)
    		for(j=1;j<=m;j++)
    			if(mp[i][j]=='1')
    			{
    				dfs1(i,j);
    				return true;
    			}
    	return false;	
    }
    
    bool checkblock1()
    {
    	int i,j;
    	for(i=1;i<=n;i++)
    		for(j=1;j<=m;j++)
    			if(mp[i][j]=='1' && tag1[i][j]==0)
    				return false;
    	return true;
    }
    
    int dfs2(int x,int y)
    {
    	int i,j,xx,yy,ret=1;
    	tag0[x][y]=1;
    	for(i=0;i<4;i++)
    	{
    		xx=x+dx[i];
    		yy=y+dy[i];
    		if(check(xx,yy)==false)
    		{
    			ret=0;
    			continue;
    		}
    		if(tag0[xx][yy] || mp[xx][yy]=='1')
    			continue;
    		if(dfs2(xx,yy)==0)
    			ret=0;
    	}
    	return ret;
    }
    
    int getblock0()
    {
    	int ret=0,i,j;
    	for(i=1;i<=n;i++)
    		for(j=1;j<=m;j++)
    			if(mp[i][j]=='0' && tag0[i][j]==0)
    				ret+=dfs2(i,j);
    	return ret;
    }
    
    int solve()
    {
    	int i,j;
    	if(gettag1()==false)
    		return -1;
    	if(checkblock1()==false)
    		return -1;
    	int cnt=getblock0();
    	if(cnt==0)
    		return 1;
    	if(cnt==1)
    		return 0;
    	return -1;
    }
    
    void init()
    {
    	memset(tag1,0,sizeof(tag1));
    	memset(tag0,0,sizeof(tag0));
    }
    
    int main()
    {
    	int i,j;
    	while(scanf("%d%d",&n,&m)!=EOF)
    	{
    		for(i=1;i<=n;i++)
    			scanf("%s",mp[i]+1);
    		init();
    		printf("%d
    ",solve());
    	}
    	return 0;
    }
    

      

     

  • 相关阅读:
    POJ2778 DNA Sequence AC自动机上dp
    codeforces732F Tourist Reform 边双联通分量
    codeforces786B Legacy 线段树优化建图
    洛谷P3588 PUS 线段树优化建图
    codeforces1301D Time to Run 模拟
    codeforces1303B National Project 二分或直接计算
    codeforces1303C Perfect Keyboard 模拟或判断欧拉路
    codeforces1303D Fill The Bag 二进制应用+贪心
    python之路——使用python操作mysql数据库
    python之路——mysql索引原理
  • 原文地址:https://www.cnblogs.com/FxxL/p/7376679.html
Copyright © 2011-2022 走看看