这套题体验极差。

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;
}

  

 

05-11 10:53
查看更多