比赛总结
这次比赛和上次发挥得差不多,做了四个题,比较不爽的是其中两个题因为没读清楚题都wa了样例,这里损失了点罚时
提交记录
在正式和非正式选手中排名144名(可以看出我的罚时有多么惨了吧233,每个题的得分基本上打了一半的折扣)
在正式选手里排名15名
A. Combination Lock
题目链接
http://codeforces.com/contest/540/problem/A
题目大意
给你一个大小为 n 的密码锁,每次转动(0->1,1->2…9->0,1->0…)需要一单位时间,给你密码锁初始状态和终止状态,问最少要操作多长时间才行。
思路
水题,不解释
代码
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
using namespace std;
char s[1100];
int st[1100],ed[1100];
int main()
{
int n,ans=0;
scanf("%d",&n);
scanf("%s",s+1);
for(int i=1;i<=n;i++)
st[i]=s[i]-'0';
scanf("%s",s+1);
for(int i=1;i<=n;i++)
ed[i]=s[i]-'0';
for(int i=1;i<=n;i++)
{
int t=abs(st[i]-ed[i]);
t=min(t,st[i]+10-ed[i]);
t=min(t,ed[i]+10-st[i]);
ans+=t;
}
printf("%d\n",ans);
return 0;
}
B. School Marks
题目链接
http://codeforces.com/contest/540/problem/B
题目大意
给你一个长度为
思路
我们对已经填好的前
k
项进行排序,问题转变为在这个有序序列里不断地加入
代码
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <map>
#define MAXN 1100
using namespace std;
int a[MAXN],tmp[MAXN];
int n,K,P,L,R,sum=0;
int main()
{
scanf("%d%d%d%d%d",&n,&K,&P,&R,&L);
for(int i=1;i<=K;i++) scanf("%d",&a[i]),tmp[i]=a[i],sum+=a[i];
if(sum+n-K>R)
{
printf("-1\n");
return 0;
}
for(int i=K+1;i<=n;i++)
{
if(sum+L+n-i<=R)
{
a[i]=L;
sum+=L;
}
else
{
a[i]=1;
sum++;
}
tmp[i]=a[i];
}
sort(tmp+1,tmp+n+1);
if(tmp[(1+n)/2]>=L)
{
for(int i=K+1;i<=n;i++) printf("%d ",a[i]);
printf("\n");
}
else printf("-1\n");
return 0;
}
C. Ice Cave
题目链接
http://codeforces.com/contest/540/problem/C
题目大意
给你一个
思路
直接BFS就好了,如果碰见已经变成了’X’的 (xt,yt) 就表明存在这样的路线,否则如果当前的格子是’X’就不继续拓展,否则继续往四个方向分别拓展移动
为什么这样做就是对的呢?因为如果最先存在一条走到还是’.’的格子 (xt,yt) ,就可以继续走,并转一圈回到’X’。之后走到已经变为’X’的 (xt,yt) 的路线的话,肯定是围绕着最开始的那个路径的终点绕了一圈,正好就给 (xt,yt) 留了几个空格(最少三个),就能绕一圈走回来了
代码
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <map>
#define MAXN 610
using namespace std;
int n,m;
char mp[MAXN][MAXN];
int sx,sy,tx,ty;
pair<int,int> q[MAXN*MAXN*4];
int xx[]={1,-1,0,0},yy[]={0,0,1,-1};
bool inMap(int i,int j)
{
if(i<1||i>n||j<1||j>m) return false;
return true;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%s",mp[i]+1);
scanf("%d%d",&sx,&sy);
scanf("%d%d",&tx,&ty);
int h=0,t=1;
q[h]=make_pair(sx,sy);
while(h<t)
{
pair<int,int>now=q[h++];
int nowx=now.first,nowy=now.second;
for(int dir=0;dir<4;dir++)
{
int nextx=nowx+xx[dir],nexty=nowy+yy[dir];
if(!inMap(nextx,nexty)) continue;
if(mp[nextx][nexty]=='X')
{
if(nextx==tx&&nexty==ty)
{
printf("YES\n");
return 0;
}
continue;
}
mp[nextx][nexty]='X';
q[t++]=make_pair(nextx,nexty);
}
}
printf("NO\n");
return 0;
}
D. Bad Luck Island
题目链接
http://codeforces.com/contest/540/problem/D
题目大意
现在有
r
个石头,
思路
显然是个概率DP题。用
代码
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <map>
#define MAXN 610
using namespace std;
double f[110][110][110];
int r,s,p;
double DFS(int i,int j,int k)
{
if(f[i][j][k]) return f[i][j][k];
//if(!i&&!j&&!k) continue;
//if(i==r&&j==s&&k==p) continue;
if(j+1<=s&&i) f[i][j][k]+=DFS(i,j+1,k)*(double)(i*(j+1))/(double)(i*(j+1)+(j+1)*k+k*i);
if(k+1<=p&&j) f[i][j][k]+=DFS(i,j,k+1)*(double)(j*(k+1))/(double)(i*j+j*(k+1)+(k+1)*i);
if(i+1<=r&&k) f[i][j][k]+=DFS(i+1,j,k)*(double)((i+1)*k)/(double)((i+1)*j+j*k+k*(i+1));
return f[i][j][k];
}
int main()
{
scanf("%d%d%d",&r,&s,&p);
f[r][s][p]=1;
double ans1=0,ans2=0,ans3=0;
for(int i=1;i<=r;i++) ans1+=DFS(i,0,0);
for(int i=1;i<=s;i++) ans2+=DFS(0,i,0);
for(int i=1;i<=p;i++) ans3+=DFS(0,0,i);
printf("%.11lf %.11lf %.11lf\n",ans1,ans2,ans3);
return 0;
}
E. Infinite Inversions
题目链接
http://codeforces.com/contest/540/problem/E
题目大意
给你一个无限长的序列
1,2,3...
,以及
q
个操作,每次操作会交换这个序列里下标为
思路
假如每次操作的下标的范围是在
所以我们可以用map来模拟交换元素的操作,然后对被修改过的那些序列元素做离散化,得到这些被修改的数字的排名、以及排名为
i
的数字是什么,然后我们可以离散化出一个新的序列,这个序列长度最多为
看下面这个序列:
6 2 3 4 9 1 7 8 5
对于第一个数字6而言,它现在在位置1,原来在位置6,
[1,6]
区间里,有3个被操作过的数字,还有3个是没有被操作过的数字,因此给最终答案贡献3
以此类推,我们枚举被修改的每个数字,找到它当前所在的下标和初始的下标之间的区间里有多少个没被操作过的数字,添加进答案
代码
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <map>
#define MAXN 410000
#define lowbit(x) ((x)&(-(x)))
using namespace std;
typedef long long int LL;
map<int,int>mp,mp2; //mp2[i]=数字i的排名
map<int,int>::iterator it,it2;
LL bit[MAXN];
int n;
void update(int x,LL val)
{
while(x<=n)
{
bit[x]+=val;
x+=lowbit(x);
}
}
LL query(int x)
{
LL ans=0;
while(x)
{
ans+=bit[x];
x-=lowbit(x);
}
return ans;
}
int a[MAXN]; //a[]里保存的是离散化后的序列
pair<int,int> opt[MAXN];
int sta[MAXN*2],top=0; //sta[i]=排名为i的数字
bool cmp(int x,int y)
{
return sta[x]<sta[y];
}
LL ans=0;
int main()
{
int q;
scanf("%d",&q);
for(int i=1;i<=q;i++)
{
int x,y;
scanf("%d%d",&x,&y);
it=mp.find(x);
it2=mp.find(y);
if(it==mp.end()) mp[x]=x;
if(it2==mp.end()) mp[y]=y;
opt[i]=make_pair(x,y);
it=mp.find(x);
it2=mp.find(y);
swap(it->second,it2->second);
}
for(it=mp.begin();it!=mp.end();it++)
mp2[it->second]=++top,sta[top]=it->second;
/*for(it=mp2.begin();it!=mp2.end();it++)
cout<<"num: "<<it->first<<"rank: "<<it->second<<endl;*/
for(int i=1;i<=top;i++) a[i]=i;
for(int i=1;i<=q;i++)
swap(a[mp2[opt[i].first]],a[mp2[opt[i].second]]);
n=top;
for(int i=n;i>=1;i--)
{
ans+=query(a[i]-1);
update(a[i],1);
}
for(it=mp.begin();it!=mp.end();it++)
ans+=abs(it->second-it->first)-abs(mp2[it->second]-mp2[it->first]);
printf("%I64d\n",ans);
return 0;
}