昨天没写,今天补上。
集训的人确实多,机房坐满了,所以我们这些人只能坐在别的桌子上,用我们的笔记本听课,而且老师讲课的时候只能看别人的电脑。
Day1——模拟
昨天一天就只讲了这个,虽然课是从下午开始上的。
模拟是不需要策略 的,只需按照题意去模拟就行了。所以也就对我们读题有所要求——读题一定要仔细,不然很有可能漏了条件,导致丢了很多的分。当然,你没看清还能过样例是很正常的,毕竟样例很多都是坑人蒙人的。
事实证明模拟题是很恶心的一种题型。是码农题的来源之一。我昨天就只刷了两题模拟。
======================================
T1黑色星期五
题目描述】一个引人深思的问题,十三号是星期五的几率比是其他星期的几率都小?所以,自然而然地,就让你统计从1900开始,每个星期一、二、三、四、五、六、天为十三号的总数。 (注意:1900年1月1日是星期一)
题解】因为模拟题没有什么思维,不用思考策略,所以就有很多的细节需要注意。比如这题,首先,你要一年一年的模拟下去。但是,还要注意闰年。闰年的判断在OJ第一页的#20判断闰年。
代码如下
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n,m;
int a[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};//每个月的天数赋值。在这里赋值比较简洁。否则会有很壮观的一片
int b[10]={};
cin>>n;
for (int i=1900;i<=1900+n-1;i++)//模拟从1900年开始,枚举年份到之后的n年
{
a[2]=28;
if ((i%4==0&&i%100!=0)||i%400==0) a[2]=29;//如果是闰年,二月份要变为29天。四年一闰百年不闰,四百年再闰
for (int j=1;j<=12;j++)//枚举月份
for (int k=1;k<=a[j];k++)//枚举每月的天数
{
if (k==13) b[m]++;//如果当天是十三号,那么那个星期的日子就要累加
if (m==7) m=0;//当星期的计数器超过了7,自然要回到星期一
m++;
}
}
cout<<b[5]<<" "<<b[6]<<" "<<b[7]<<" "<<b[1]<<" "<<b[2]<<" "<<b[3]<<" "<<b[4]<<endl;//因为题目的输出顺序并不是星期一到星期天,所以要看清题目
return 0;
}
事实证明模拟是有些繁琐的
=======================================
T2两只丢失的牛
题目描述】就是两只无聊的牛逃出了农场,他们的主人要去找他们。说是两只牛,其实就只是两只合体的牛,因为他们始终是挤在一个格子里。而辛苦的农民伯伯FJ要去寻找他的牛。输入的是一个10*10的字符方阵,其中C代表双宿双飞是牛,F表示辛苦的FJ,还有 ‘*’表示障碍物。不论是牛还是人,遇到障碍物都要顺时针旋转九十度(说起来有点怪异)。
题解】这题有一个需想清楚。方阵总共有100个格子,牛每次都有上下左右4种可能性,FJ也都有上下左右4种可能性。所以如果在100*4*4次之内FJ都没有和牛相遇,则说明FJ不会找到牛了。
代码如下:
#include<bits/stdc++.h>
using namespace std;
int a1,b1,a2,b2,d1,d2;
int dx[4]={-1,0,1,0};
int dy[4]={0,1,0,-1};
int k=160500;
int s=0;
char a[15][15];
void Nextspet(int &x,int &y,int &d)
{
x+=dx[d];y+=dy[d];
if (a[x][y]=='*')
{x-=dx[d],y-=dy[d],d=(d+1)%4;}
}
int main()
{
for (int i=1;i<=10;i++)//读入
for (int j=1;j<=10;j++)
{
cin>>a[i][j];
if (a[i][j]=='C')
a1=i,b1=j;
if (a[i][j]=='F')
a2=i,b2=j;
}
for (int i=1;i<=11;i++)//在方阵外一圈再加上障碍物,就不用再判断是否到头
a[i][0]=a[i][11]=a[0][i]=a[11][i]='*';
for (;(a1!=a2||b1!=b2)&&s<k;s++)
{
Nextspet(a1,b1,d1);//判断牛下一步该如何走
Nextspet(a2,b2,d2);//判断FJ下一步该如何走
}
if (s<k) cout<<s;//如果在s秒内遇见,则输入相遇的时间
else cout<<0;//否则输出0,表示永远都不会相遇。也就是死循环
return 0;
}
=====================================
还有恶心的字符串展开。差点没让我吐血。首先题目就是壮观的一大片。看得一脸懵逼。然后打起来的细节简直不要太多。
题目描述】先输入p1,p2,p3,再输入包含小写字母和数字还有“—”的字符串。当遇到“—”的时候要按照规则展开,展开‘—’左右两个之间的字母或数字。
规则:p1是1 的时候,展开的为小写字母,如果是2展开的是大写字母,如果是3,不管“—”左右是数字还是字母,中间都用*填充。
如果p2=?填充的字母或数字每个就要重复?遍。
当p3=1时按照原来的顺序输出,当p3=2是按照逆序输出
还有,如果“—”的后面刚好就是前面字母或数字的后一个,只需直接去掉“—”就可以了,如果“—”前后两个都是一样,则不需要改变
具体代码如下:
#include<bits/stdc++.h>
using namespace std;
int p1,p2,p3;
string s;
int m,n;
bool a2(char l)
{
if (l>='0'&&l<='9') return true;
else return false;
}
bool a3(char l1)
{
if (l1>='a'&&l1<='z') return true;
else return false;
}
bool a1(char x1,char x2)//判断是否符合条件:是否同为数字或字符,且前面的小于后面的
{
if (a2(x1)&&a2(x2)&&x1<x2) return true;
if (a3(x1)&&a3(x2)&&x1<x2) return true;
return false;
}
int main()
{
cin>>p1>>p2>>p3;
cin>>s;
cout<<s[0];
int z=s.size();
for (int i=1;i<=z-2;i++)
{
if (s[i]=='-')
{
m=s[i-1];
n=s[i+1];
if (a1(s[i-1],s[i+1]))
{
if (p1==2)
if (a3(s[i-1]))
{
m+='A'-'a';
n+='A'-'a';
}
if (p3==1)
for (char j=m+1;j<n;j++)
for (char k=1;k<=p2;k++)
if (p1==3)
cout<<"*";
else cout<<j;
else
for (char j=n-1;j>=m+1;j--)
for (int k=1;k<=p2;k++)
if (p1==3)
cout<<"*";
else cout<<j;
}
else cout<<'-';
}
else cout<<s[i]; //如果不是“—”直接输出
}
cout<<s[s.size()-1]<<endl;//输出最后一位
return 0;
}