VK-Cup,cf里面只有切成俄文才能看到,题目也都是俄文的(百度翻译成英文和中文).
两人组队参赛的,赛期1天,乐多赛赛制(和时间基本无关,交上去挂了扣分)。这次是第一场资格赛。
这次又和ditoly大佬组队啦,队名不知道该叫什么,因为我们真的菜,就取了个名字叫vegetable chicken(菜鸡)
但是题目不会很难,所以都一次过了(真的舒服)
-----------------------------------我是分割线
A.Год поступления в университет(我也不知道是什么啊,我也很绝望啊)
题意:有一个人参加了n(n<=5)个兴趣小组,然后它的入学年份和参加年份差距不会超过x(这东西不告诉你),求入学年份。
做题情况:根本看不懂题意,去问了学长才知道。
题解:最大值加最小值除2
ditoly的代码真的风骚
#include<iostream> #include<algorithm> using namespace std; int main() { int n,x,a=0,b=2333; for(cin>>n;n--;)cin>>x,a=max(a,x),b=min(b,x); cout<<((a+b)>>1); }
B. Новость о зачёте(我要是知道这个是什么,我还会这么绝望吗?)
题意:有n个人,第一个人知道了一条消息,每个人最多发送ai条消息,你要让所有人都知道这个消息,求一个方案即可。
题解:贪心一下,每次发给能发最多消息的人。
#include<iostream> #include<cstdio> #include<algorithm> #include<queue> #include<cstring> #include<map> #define MAXN 600000 using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();} return x*f; } int a[1005],n,cnt=0; int ans[2][1000]; struct node{ int a,num; friend bool operator< (node x,node y) { return x.a<y.a; } }; queue<int> q; priority_queue<node> q2; int main() { n=read();for(int i=1;i<=n;i++)a[i]=read(); for(int i=1;i<=a[1];i++)q.push(1); for(int i=2;i<=n;i++)q2.push((node){a[i],i}); while(!q.empty()&&n>1) { int u=q.front();q.pop(); node v=q2.top();q2.pop(); ans[0][++cnt]=u;ans[1][cnt]=v.num; for(int i=1;i<=v.a;i++)q.push(v.num); n--; } if(n!=1) return 0*puts("-1");printf("%d\n",cnt); for(int i=1;i<=cnt;i++) printf("%d %d\n",ans[0][i],ans[1][i]); return 0; }
C.Цикл в лабиринте(警察叔叔,就是它让我绝望的!)
题意:有一张网格图,有一些点是障碍,有一个机器人在某一个点,每次可以上下左右走,要走k次之后回到起点,求一个字典序最小(D,L,R,U)的方案6
n,m<=1000,k<=10^6
题解:bfs一下每个点到起点的最短距离,每次按字典序搜,能走就走。
#include<iostream> #include<cstdio> #include<algorithm> #include<queue> #include<cstring> #include<map> using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();} return x*f; } int n,m,x=0,y=0,k; char s[1005][1005]; int d[1005][1005]; char ans[1000005]; struct node{ int x,y; }newx; queue<node> q; const int dis[4][2]={{1,0},{-1,0},{0,1},{0,-1}}; void bfs() { q.push((node){x,y});d[x][y]=1; while(!q.empty()) { newx=q.front();q.pop(); for(int i=0;i<4;i++) { int xx=newx.x+dis[i][0]; int yy=newx.y+dis[i][1]; if(xx<1||yy<1||xx>n||yy>m||d[xx][yy]||s[xx][yy]=='*') continue; d[xx][yy]=d[newx.x][newx.y]+1; q.push((node){xx,yy}); } } } int main() { n=read();m=read();k=read(); for(int i=1;i<=n;i++)scanf("%s",s[i]+1); for(int i=1;i<=n&&!x;i++) for(int j=1;j<=m&&!x;j++) if(s[i][j]=='X') {x=i;y=j;s[i][j]='.';} bfs(); for(int i=1;i<=k;i++) { if(x<n&&s[x+1][y]=='.'&&d[x+1][y]<=k-i+1){ans[i]='D';++x;continue;} if(y>1&&s[x][y-1]=='.'&&d[x][y-1]<=k-i+1){ans[i]='L';--y;continue;} if(y<m&&s[x][y+1]=='.'&&d[x][y+1]<=k-i+1){ans[i]='R';++y;continue;} if(x>1&&s[x-1][y]=='.'&&d[x-1][y]<=k-i+1){ans[i]='U';--x;continue;} return 0*puts("IMPOSSIBLE"); } for(int i=1;i<=k;i++)printf("%c",ans[i]); return 0; }
D.
给定n个数和k,求有多少对(x,y)满足x<y且第x个数和第y个数二进制下有k位不同。n<=200000,k<=14,ai<=10000
题解:搜索出所有k位的二进制数,最多3500左右,然后枚举ai判断。
复杂度2^14+10000*3500
#include<iostream> #include<cstdio> #include<algorithm> #include<queue> #include<cstring> #include<map> #define ll long long using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();} return x*f; } int a[20]; int s[10005]; int num[10005]; ll ans=0; int n,k,cnt=0; void dfs(int i,int j,int x) { if(i==15){if(j==k)s[++cnt]=x;return;} dfs(i+1,j,x); dfs(i+1,j+1,x|a[i]); } int main() { a[1]=1;for(int i=2;i<=14;i++)a[i]=a[i-1]<<1; n=read();k=read(); dfs(1,0,0); for(int i=1;i<=n;i++){int x=read();num[x]++;} for(int i=0;i<=10000;i++)if(num[i]) for(int j=1;j<=cnt;j++) {int x=i^s[j];if(x>10000)continue; if(k!=0) ans+=1LL*num[i]*num[x]; else ans+=1LL*num[i]*(num[i]-1); } cout<<(ans>>1); return 0; }