2017-10-6 清北刷题冲刺班p.m
Posted Soda
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2017-10-6 清北刷题冲刺班p.m相关的知识,希望对你有一定的参考价值。
1.数组异或
#include<iostream> #include<cstdio> #define maxn 100010 #define mod 1000000007 using namespace std; int n,a[maxn],b[maxn],c[maxn]; int main(){ freopen("xorarray.in","r",stdin);freopen("xorarray.out","w",stdout); scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&a[i]); for(int i=1;i<=n;i++)scanf("%d",&b[i]); c[1]=a[1]^b[1]; for(int i=2;i<=n;i++){ c[i]=c[i-1]; for(int j=1;j<i;j++){ c[i]+=a[i]^b[j]; if(c[i]>=mod)c[i]-=mod; } for(int j=1;j<i;j++){ c[i]+=a[j]^b[i]; if(c[i]>=mod)c[i]-=mod; } c[i]+=a[i]^b[i]; if(c[i]>=mod)c[i]-=mod; } for(int i=1;i<=n;i++)printf("%d ",c[i]); fclose(stdin);fclose(stdout); return 0; }
/* 累计所有数二进制下的每一位0或1的个数 又因为是xor,所以a[j][0]*b[j][1]+a[j][1]*b[j][0] */ #include<iostream> #include<cstdio> #define maxn 100010 #define mod 1000000007 using namespace std; int n,A[maxn],B[maxn]; int a[32][2],b[32][2],C[maxn]; int main(){ //freopen("Cola.txt","r",stdin); freopen("xorarray.in","r",stdin);freopen("xorarray.out","w",stdout); scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&A[i]); for(int i=1;i<=n;i++)scanf("%d",&B[i]); for(int i=1;i<=n;i++){ for(int j=0;j<=30;j++){ a[j][(A[i]>>j)&1]++; b[j][(B[i]>>j)&1]++; long long c=(1LL*a[j][1]*b[j][0]%mod+1LL*a[j][0]*b[j][1]%mod)%mod; c=c*(1<<j)%mod; C[i]=(C[i]+c)%mod; } } for(int i=1;i<=n;i++)printf("%d ",C[i]); return 0; }
2.侦探游戏(最小生成树,期望)
#include<iostream> #include<cstdio> #include<queue> #include<cstring> #define maxn 20010 using namespace std; int n,m,num,head[maxn],dis[maxn],D[maxn]; double ans,w; bool v[maxn]; struct node{ int to,pre,v; }e[100010*2]; void Insert(int from,int to,int v){ e[++num].to=to; e[num].v=v; e[num].pre=head[from]; head[from]=num; } void spfa(int s1,int s2){ queue<int>q; memset(v,0,sizeof(v));memset(dis,127/3,sizeof(dis)); v[s1]=1;v[s2]=1;dis[s1]=0;dis[s2]=0; if(!v[1])v[1]=1,dis[1]=0,q.push(1); q.push(s1);q.push(s2); while(!q.empty()){ int now=q.front();q.pop();v[now]=0; for(int i=head[now];i;i=e[i].pre){ int to=e[i].to; if(dis[to]>dis[now]+e[i].v){ dis[to]=dis[now]+e[i].v; if(!v[to]){ v[to]=1; q.push(to); } } } } for(int i=1;i<=n;i++){ ans+=(double)dis[i]*w; } int k=min(D[s1],D[s2]); ans+=(double)k*w; } void SPFA(int s){ queue<int>q; memset(v,0,sizeof(v)); memset(D,127/3,sizeof(D)); v[s]=1;D[s]=0; q.push(s); while(!q.empty()){ int now=q.front();q.pop();v[now]=0; for(int i=head[now];i;i=e[i].pre){ int to=e[i].to; if(D[to]>D[now]+e[i].v){ D[to]=D[now]+e[i].v; if(!v[to]){ v[to]=1; q.push(to); } } } } } int main(){ //freopen("Cola.txt","r",stdin); freopen("detective.in","r",stdin);freopen("detective.out","w",stdout); scanf("%d%d",&n,&m); w=(double)(n*(n-1))/2.0; w=1.0/w; int x,y,z; for(int i=1;i<=m;i++){ scanf("%d%d%d",&x,&y,&z); Insert(x,y,z);Insert(y,x,z); } SPFA(1); for(int i=1;i<=n;i++){ for(int j=1;j<i;j++){ spfa(i,j); } } printf("%.2lf",ans); /*int sz=sizeof(head)+sizeof(e); cout<<sz/1048576;*/ }
/* 暴力算法: 求一遍最小生成树,枚举两个点,想象将两个点连上权值为0的边,然后进行倍增,求两点之间最长的一条边,删除这条边,当前树上所有边权和即为此时的花费,最后除以n*(n-1) */
/* 枚举哪一条边可以删掉,由于克鲁斯卡尔最小生成树边是按从大到小顺序选入的,所以当前讨论的这条边一定是图上最大的边,而且既然他是最小生成树的一条边,他所连接的两个集合一定是两个树,将两棵树大小进行乘法原理,累计答案 (我在胡言乱语什么) */ #include<iostream> #include<cstdio> #include<algorithm> #define maxn 20010 #define maxm 100010 using namespace std; struct node{ int from,to,v; bool operator < (const node a)const{ return v<a.v; } }e[maxm]; int n,m,fa[maxn],s[maxn]; unsigned long long sum,cnt; int find(int a){ if(a==fa[a])return a; return fa[a]=find(fa[a]); } int main(){ //freopen("Cola.txt","r",stdin); freopen("detective.in","r",stdin);freopen("detective.out","w",stdout); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)fa[i]=i,s[i]=1; for(int i=1;i<=m;i++)scanf("%d%d%d",&e[i].from,&e[i].to,&e[i].v); sort(e+1,e+m+1); for(int i=1;i<=m;i++){ int x=find(e[i].from),y=find(e[i].to); if(x==y)continue; cnt+=1ULL*s[x]*s[y]*e[i].v; sum+=e[i].v; fa[y]=x;s[x]+=s[y]; } double ans=sum-cnt/((n*(n-1))/2.0); //double ans = sum - 2.0 * cnt / n / (n - 1); printf("%.2lf",ans); return 0; }
3.棋盘迷宫(分治,搜索)
#include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; int n,m,x1,x2,y1,y2,e[2][2]={{0,1},{1,0}}; char map[510][510]; bool vis[250010]; int f(int x,int y){ return (x-1)*m+y; } bool BFS(){ queue<int>q; memset(vis,0,sizeof(vis)); vis[f(x1,y1)]=1; q.push(f(x1,y1)); while(!q.empty()){ int now=q.front();q.pop(); int x=(now-1)/m+1,y=now-(x-1)*m; for(int i=0;i<2;i++){ int xx=x+e[i][0],yy=y+e[i][1]; int w=f(xx,yy); if(xx==x2&&yy==y2)return 1; if(xx>=1&&xx<=n&&yy>=1&&yy<=n&&xx<=x2&&yy<=y2&&!vis[w]&&map[xx][yy]==\'.\'){ vis[w]=1; q.push(w); } } } return 0; } int main(){ //freopen("Cola.txt","r",stdin); freopen("boardgame.in","r",stdin);freopen("boardgame.out","w",stdout); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%s",map[i]+1); int q; scanf("%d",&q); while(q--){ scanf("%d%d%d%d",&x1,&y1,&x2,&y2); if(x2<x1||y2<y1){ printf("No\\n"); continue; } if(x1==x2){ bool flag=0; for(int i=y1;i<=y2;i++){ if(map[x1][i]==\'#\'){ flag=1; printf("No\\n");break; } } if(!flag)printf("Yes\\n"); continue; } if(y1==y2){ bool flag=0; for(int i=x1;i<=x2;i++){ if(map[i][y1]==\'#\'){ flag=1; printf("No\\n");break; } } if(!flag)printf("Yes\\n"); continue; } int fl=BFS(); if(fl)printf("Yes\\n"); else printf("No\\n"); } fclose(stdin);fclose(stdout); return 0; }
/* 考试的时候忘记判断起点和终点是否合法了 */ #include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; int n,m,x1,x2,y1,y2,e[2][2]={{0,1},{1,0}}; char map[510][510]; bool vis[250010]; int f(int x,int y){ return (x-1)*m+y; } bool BFS(){ queue<int>q; memset(vis,0,sizeof(vis)); vis[f(x1,y1)]=1; q.push(f(x1,y1)); while(!q.empty()){ int now=q.front();q.pop(); int x=(now-1)/m+1,y=now-(x-1)*m; for(int i=0;i<2;i++){ int xx=x+e[i][0],yy=y+e[i][1]; int w=f(xx,yy); if(xx>=1&&xx<=n&&yy>=1&&yy<=n&&xx<=x2&&yy<=y2&&!vis[w]&&map[xx][yy]==\'.\'){ if(xx==x2&&yy==y2)return 1; vis[w]=1; q.push(w); } } } return 0; } int main(){ //freopen("Cola.txt","r",stdin); freopen("boardgame.in","r",stdin);freopen("boardgame.out","w",stdout); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%s",map[i]+1); int q; scanf("%d",&q); while(q--){ scanf("%d%d%d%d",&x1,&y1,&x2,&y2); if(x2<x1||y2<y1){ printf("No\\n"); continue; } if(x1==x2){ bool flag=0; for(int i=y1;i<=y2;i++){ if(map[x1][i]==\'#\'){ flag=1; printf("No\\n");break; } } if(!flag)printf("Yes\\n"); continue; } if(y1==y2){ bool flag=0; for(int i=x1;i<=x2;i++){ if(map[i][y1]==\'#\'){ flag=1; printf("No\\n");break; } } if(!flag)printf("Yes\\n"); continue; } if(map[x1][y1]==\'#\'){ printf("No\\n"); continue; } int fl=BFS(); if(fl)printf("Yes\\n"); else printf("No\\n"); } fclose(stdin);fclose(stdout); return 0; }
以上是关于2017-10-6 清北刷题冲刺班p.m的主要内容,如果未能解决你的问题,请参考以下文章