2017"百度之星"程序设计大赛 - 初赛(A) [ hdu 6108 小C的倍数问题 ] [ hdu 6109 数据分割 ] [ hdu 6110 路径交 ] [ hdu 6112 今夕何夕 ] [ hdu 6113 度度熊的01世界 ]

这套题体验极差。

 

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\n",lanswer);
	for(i=1;i<=lanswer;i++)
		printf("%d\n",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\n",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\n",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\n",solve());
	}
	return 0;
}

  

 

 

 

posted @ 2017-08-16 23:48  太阳星人FxxL  阅读(516)  评论(0编辑  收藏  举报