您的位置:首页 > 其它

百度之星2017初赛题解(A)

2017-08-13 21:14 337 查看
T1:

简单数论,问满足(a0+a1*B+...+an*B^n)=a0+a1+...+an(mod P)的P的个数

即满足P|(B-1)a1+(B^2-1)a2+(B^3-1)a3+...,即P|B-1的P的个数

sqrt(B-1)暴力枚举B-1约数即可

T2:

现在给若干个条件,xi=xj或xi≠xj,要你将它们划分成若干组,满足每个组除去最后一个条件时成立,否则不成立。

拿并查集将所有相等的点缩起来,对于每个连通块,挂一个vector或者set储存与他不相等的连通块编号(即并查集的代表元)

启发式合并,每次将vector小的合并到大的中去,复杂度O(nlognα(n))或O(nlog^2nα(n))(实际不满)

PS:SB出题人认为最后一组到最后一个条件若成立就不输出

#include<bits/stdc++.h>
#include<tr1/unordered_set>
#define maxn 200100
using namespace std;
typedef long long ll;
set<ll>st2[maxn];
typedef set<ll>::iterator sit;
int L,T,cnt[maxn],f[maxn],A[maxn],B[maxn],C[maxn];
int find(int x){return x==f[x]?x:f[x]=find(f[x]);}
int main(){
scanf("%d",&L);
for(int i=1;i<=200010;++i)f[i]=i;
for(int i=1;i<=L;++i)
scanf("%d%d%d",&A[i],&B[i],&C[i]);
for(int i=1,pos;i<=L;i=pos){
for(pos=i;pos<=L;pos++){
if(C[pos]){
int x=find(A[pos]),y=find(B[pos]);
if(x==y)continue;
if(st2[x].find(y)!=st2[x].end()){
cnt[++T]=pos-i+1;
break;
}
if(st2[x].size()>st2[y].size())swap(x,y);
f[x]=y;
for(sit it=st2[x].begin();it!=st2[x].end();++it)
st2[*it].erase(x),st2[*it].insert(y),st2[y].insert(*it);
st2[x].clear();
} else {
int x=find(A[pos]),y=find(B[pos]);
if(x==y){
cnt[++T]=pos-i+1;
break;
}
st2[x].insert(y),st2[y].insert(x);
}
}
if(pos<=L)pos++;
for(int j=i;j<pos;++j)
st2[A[j]].clear(),st2[B[j]].clear(),f[A[j]]=A[j],f[B[j]]=B[j];
}
printf("%d\n",T);
for(int i=1;i<=T;++i)printf("%d\n",cnt[i]);
}

T3:
这个。。。简单题吧,

首先两条路径求交,交集一定是一条路径,一定是一个的LCA在另一条路径上,否则交集就是空

那么维护一个线段树,每个节点表示这个区间的路径求交求出的路径是什么

然后普通线段树那样做即可

T4:

给你个地图(BALABALA...)注意“*”翻转的可达性是所有格子都要翻转

这题。。。如果状压"*"的状态的话,我猜想有用的状态(即可能成为最优)不会很多

于是拿一个hash表spfa暴力DP一番(可能本质上是真·暴力

然后就过了。。。

#include<bits/stdc++.h>
#define get(x,y) ((x*100)+y)
#define inf 1000000007
using namespace std;
typedef unsigned long long ull;
typedef pair<int,bool> par;
ull h(ull id,ull S){return S*19260817+id;}
unordered_map<ull,par>dp;
queue<pair<int,ull> >q;
char c[100][100];
int T,n,m,cas,id[100][100],dx[4]={0,0,1,-1},dy[4]={1,-1,0,0},flag,edx,edy;
ull pre[100][100];
int main(){
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
dp.clear();
int ans=inf,x0=0,x1=0,bg,ed;
for(int i=1;i<=n;++i){
scanf("%s",c[i]+1);
for(int j=1;j<=m;++j)
if(c[i][j]=='S')bg=get(i,j);
else if(c[i][j]=='E')edx=i,edy=j;
}
x1=0,flag=1;
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
if(c[i][j]=='*')id[i][j]=++x1;
else id[i][j]=0;
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j){
pre[i][j]=0;
for(int k=0;k<4;++k){
int ni=i+dx[k],nj=j+dy[k];
if(ni<=0||nj<=0||ni>n||nj>m)continue;
if(c[ni][nj]=='*')pre[i][j]|=1ull<<id[ni][nj];
}
}
q.push(make_pair(bg,0ull)),dp[h(bg,0)].first=1;
while(q.size()){
pair<int,ull> u=q.front();q.pop();
int x,y,p=dp[h(u.first,u.second)].first;
ull s;
dp[h(u.first,u.second)].second=0;
x=u.first/100,y=u.first%100,s=u.second;
// printf("<%d,%d,%llu,%d>\n",x,y,s,p);
if(p+abs(x-edx)+abs(y-edy)>=ans)continue;

for(int i=0;i<4;++i){
int nx=x+dx[i],ny=y+dy[i];ull _s=s;
if(nx<=0||ny<=0||nx>n||ny>m)continue;
if((__builtin_popcount(s&pre[nx][ny])&1)^(c[nx][ny]=='x'))continue;
if(c[nx][ny]!='.'&&c[nx][ny]!='x'){
if(c[nx][ny]=='E'&&(s&1)){
ans=min(ans,p+1);
} else if(c[nx][ny]=='*'){
_s^=(1ull<<id[nx][ny]);
} else if(c[nx][ny]=='K'){
_s|=1;
}
}
ull S=h(get(nx,ny),_s);
int& _q=dp[S].first;
if(!_q||_q>p+1){
_q=p+1;
if(_q>=ans)continue;
if(dp[S].second)continue;
dp[S].second=1,q.push(make_pair(get(nx,ny),_s));
}
}
}
printf("Case #%d:\n%d\n",++cas,ans==inf?-1:ans-1);
}
}

T5:
不想说了,2-29写成2-30,智商-1

T6:

不想说了,bfs/dfs判一下连通块即可

#include<bits/stdc++.h>
using namespace std;
char c[110][110];
int n,m,vis[110][110],flag;
void dfs(int x,int y,int z){
if(vis[x][y])return ;
if(x<=0||y<=0||x>n||y>m){flag=1;return ;}
if(c[x][y]!=z)return ;
vis[x][y]=1;
dfs(x+1,y,z),dfs(x,y+1,z),dfs(x-1,y,z),dfs(x,y-1,z);
}
int main(){
while(scanf("%d%d",&n,&m)==2){
for(int i=1;i<=n;++i)
scanf("%s",c[i]+1);
for(int i=0;i<=n+5;++i)
for(int j=0;j<=m+5;++j)
vis[i][j]=0;
int x0=0,x1=0,_x0=0;
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j){
if(!vis[i][j]){
flag=0,dfs(i,j,c[i][j]);
if(c[i][j]=='1'){
x1++;
} else {
x0++;
if(!flag)_x0++;
}
}
}
// printf("[%d,%d,%d]",x0,x1,_x0);
if(_x0==1&&x1==1)printf("0\n");
else if(_x0==0&&x1==1)printf("1\n");
else printf("-1\n");
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: