【模拟】模拟题杂集

努力的每一天都是如此的充实

1.UPC Contest2258 - 抗击疫情 训练赛第五十三场 I:Box and Ball

题目描述
We have N boxes, numbered 1 through N. At first, box 1 contains one red ball, and each of the other boxes contains one white ball.

Snuke will perform the following M operations, one by one. In the i-th operation, he randomly picks one ball from box xi, then he puts it into box yi.

Find the number of boxes that may contain the red ball after all operations are performed.

Constraints
2≤N≤105
1≤M≤105
1≤xi,yi≤N
xi≠yi
Just before the i-th operation is performed, box xi contains at least 1 ball.
输入
The input is given from Standard Input in the following format:

N M
x1 y1
:
xM yM
输出
Print the number of boxes that may contain the red ball after all operations are performed.
样例输入
3 2
1 2
2 3
样例输出
2
提示
Just after the first operation, box 1 is empty, box 2 contains one red ball and one white ball, and box 3 contains one white ball.

Now, consider the second operation. If Snuke picks the red ball from box 2, the red ball will go into box 3. If he picks the white ball instead, the red ball will stay in box 2. Thus, the number of boxes that may contain the red ball after all operations, is 2

最近总是被这些个模拟题困住,难受哎,来写个博客提提醒吧

解题思路:用一个tal数组来记录第i个框中剩余几个小球 ,拿出tal [ i ]就减一,tal [ i ] 放入就加一 , 这里的 i 指的是第 i 个框;然后还需要用一个flag数组来记录第 i 个框有没有可能有红球,如果tal[ i ]==0的话,原来flag[i]等于1的话,要更改为0,没有球了,当然就不可能有红色球的存在了。最后遍历1到n的每一个框,若flag[i]==1的话,计数器加一就行了,具体可见代码

#include<bits/stdc++.h>
using namespace std;
int x[101011],y[101011],tal[101011],flag[101011];
int main()
{
	int n,m,i;
	scanf("%d%d",&n,&m);
	for(i=1;i<=n;i++)
	{
		tal[i]=1;
	}
	for(i=1;i<=m;i++)
	{
		scanf("%d%d",&x[i],&y[i]);
	}
	flag[1]=1;
	for(i=1;i<=m;i++)
	{
		tal[x[i]]--;
		tal[y[i]]++;
		if(flag[x[i]])//如果x[i]位置有红球存在的可能 就将 flag[y[i]]制为1 
			flag[y[i]]=1;
		if(tal[x[i]]==0) //框中没有球的情况 
			flag[x[i]]=0;
	}
	int count1=0;
	for(i=1;i<=n;i++)
	{
		//cout<<flag[i]<<" ";
		if(flag[i])
		{
			count1++;
		}
	}
	printf("%d",count1);
	return 0;
}

-------------------------------------------------------分割线-------------------------------------------------------------------------


2.UPC Contest2376 - 2020年春混合个人训练第一场 F:趾压板矩阵

题目描述
第二天早晨,跑男队员们来到了风景秀丽的扬州瘦西湖,刚下车他们全都尖叫起来,没错,就是他们最怕的“趾压板”:
一块超级大的趾压板被分成了n行n列,每个小格子上都有一个数字。游戏规则是:观察一段时间后,把所有的数字拿掉,分别抽取一个行号i和列号j,说出这个位置上原来的数字是多少,如果不能说出正确的值,就要接受处罚,光脚从左上角1沿着顺序从小到大走到这个数字所在位置。
在这里插入图片描述

“捡漏王”王祖蓝思考了一会,马上找到了其中的奥秘,你呢?

输入
输入共一行,包含三个整数n,i,j,每两个整数之间用空格隔开,分别表示矩阵大小、待求的数所在的行号和列号。

输出
输出共一行,包含一个整数,表示相应矩阵中第i行和第j列的数。
样例输入
7 4 3
样例输出
18
提示
对于50%的数据,1≤n≤100;
对于100%的数据,1≤n≤30,000,1≤i≤n,1≤j≤n。

这道题呢,需要先找一下这个矩阵的排布规律,然后再进行模拟一下就好了
在这里插入图片描述
对于上述有一个难点就是,怎样求某个坐标在他所在层中的序号数,简单来说就是他是第几个。这里就需要分奇偶来处理了,具体怎么求代码中有展示

上代码:

#include<bits/stdc++.h>
using namespace std;

int main()
{
	int n,x,y;
	cin>>n>>x>>y;
	int tmp=x+y-1;//位于第几层
	int cnt=tmp-1;//该坐标之前有多少层 
	int sum1=0,ans=0;
	for(int i=1;i<=cnt;i++)
	{
		if(i<=n)
		sum1+=i;
		else sum1+=n-(i%n);
	}
	ans=sum1;
	//cout<<ans<<endl;
	
	//分奇偶来处理该坐标在其所在层中的序号数  
	if(tmp%2==0)//偶数层的话就是从左下方到右上方穿过,这里所言"穿过"就是我所给图中的的那些红线 
	{
		if(tmp<=n) ans+=y;
		else if(tmp>n) ans+=y-(tmp-n);
	}
	else//奇数层的话就是从右上方到左下方穿过 
	{
		if(tmp<=n) ans+=tmp-y+1;
		else if(tmp>n) ans+=x-(tmp-n);
	}
	cout<<ans<<endl;
	return 0;
 } 

-------------------------------------------------------分割线-------------------------------------------------------------------------


3. 2020年“远光杯”粤澳计算机程序设计大赛网络资格赛 M:排除危险

问题描述:
实验老师要将购置的化学物品装箱,这些化学物品是简单化合物,每个化学物品由两种化学元素组成,用x+y表示,其中x和y是用整数表示的化学元素。装箱有一个安全隐患,如果箱子里任何n个化学物品,正好包含n种元素,那么将组成一个容易爆炸的混合物。为了安全,实验老师每拿到一个化学物都要进行判断,如果与已装箱的化学物形成易爆,就不装箱,否则就装箱。假设实验老师按照输入的顺序进行装箱,编程输出有多少个化学物没有装箱。例如1+2、2+3、1+3,三组三种元素就易爆。再如1+2, 7+2, 4+6, 1+5,四组六种元素不会易爆,但再加5+7就不行,因为1+2, 7+2, 1+5, 5+7就组成四组四种元素,所以5+7就不能装箱。

输入要求
数据包含若干行,每行输入2个整数x,y(0<=x,y<=105)代表一个由元素x和y组成的化学物品。数据用-1结尾。

化学元素和化学物品的个数不确定,但在正整数范围之内。

输出要求
输出没有装箱的化学物数量,并换行

输入

1 2
3 4
3 5
3 1
2 3
4 1
2 6
6 5
-1

输出

3

对于这道题就是每次动态记录箱子中的元素种类数和化学物个数,每次将化学物放入箱子中之前进行判断,判断的就是:如果将此化合物放入箱子中,则需判断会产生的化合物个数和元素种类数是否相等,相等的话,就代表不能放,ans++,如果不想等的话,就代表可以放入这时需更新一下,放入后箱子中的化合物个数和元素种类数,纯模拟过程,也许不是正解,但是模拟的话确实凑效,给解出来了,hh。

上代码:

#include<bits/stdc++.h>
using namespace std;
int mp[100010];
int main()
{
	int x,y,n=0,sum=0,ans=0;
	while(1)
	{
		cin>>x;
		if(x==-1) break;
		cin>>y;
		int tmp=sum;
		if(x==y&&mp[x]==0) tmp++;
		else if(x!=y&&(mp[x]==0&&mp[y]!=0)) tmp++;
		else if(x!=y&&mp[x]!=0&&mp[y]==0) tmp++;
		else if(x!=y&&mp[x]==0&&mp[y]==0) tmp+=2;
		if(tmp==n+1){
			ans++;
		} 
		else{
			mp[x]=1;
			mp[y]=1;
			sum=tmp;
			n++;
		}
	}
	cout<<ans<<endl;
	return 0;
}

--------------------------------------------------------分割线-----------------------------------------------------------------------


4. Contest2376 - 2020年春混合个人训练第一场 G:背菜谱

题目描述
扬州是中国四大菜系之一的淮扬菜系的发源地。中午,跑男们来到扬州菜根香饭店,这是家很有名的老字号,有着正宗的淮扬菜。狮子头不松不紧、蟹粉味很浓,扬州炒饭配料丰富,米粒颗颗饱满,煮干丝入口即化、汤头也很鲜……
不过吃饭前,他们还必须完成一项比赛——背菜谱,每人都有一本饭店的菜谱,在规定的时间看谁记住的菜名多。Angelababy发现菜谱中有的菜名字多一些,有的字少一些,多的菜名难背一点,少的菜名好背一点,根据Angelababy的经验,她能一眼看出背一个菜名需要的时间,以分钟记。
开始背菜谱的时间是yyyy年mm月dd日hh时min分,开始测试的时间是yyyy’年mm’月dd’日hh’时min’分。那么测试之前她最多能背多少个菜名呢?

输入
第一行一个整数n,表示字典中的单词数,n≤5000。
接下来n行,每行一个整数表示背这个单词需要用的时间,以分钟记,小于等于10000。
接下来两行依次是开始背菜谱的时间和开始测试时间。

输出
输出共一行,包含一个整数,测试前最多能背出的菜名数。
样例输入

2
1
1
2007-06-23-11:59
2007-06-23-12:00

样例输出

1

提示

对于100%的数据,1≤n≤5000。
时间给出的格式是:yyyy-mm-dd-hh:min,例如:2007-06-23-02:00,采用24小时制,每天从00:00~23:59,年份从0000到9999。

对于这道题,一开始我是想着计算两者之前所差的天数(从前一个时间开始到第二个时间)再加上所差分钟数,但是这个所差分钟数不是很好处理,所以就产生了后来的这种做法,计算前一个日期一共有多少分钟数,和后一个日期一共有多少分钟数,可能会超int范围,所以我就开了个long long类型的来记录这两个值,然后让这两个值做差,就是所差的分钟数,换句话说,也就是有这么些个时间来背菜谱。对于背菜谱,想要背更多的菜谱,就需要贪心一下,就是先背耗时短的再背耗时大的,这样就可以得到最优解,所以先对其从小到大排一下序,用一个前缀和数组来维护一下背菜谱所用时间,再和所拥有的的背菜谱时间进行比较就可得到答案。

上代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,a[5010];
ll s[5010];
int main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    sort(a+1,a+n+1);
    for(int i=1;i<=n;i++) s[i]=s[i-1]+1ll*a[i]; 
    string str1,str2;
    cin>>str1>>str2;
    int y1=(str1[0]-'0')*1000+(str1[1]-'0')*100+(str1[2]-'0')*10+str1[3]-'0';
    int y2=(str2[0]-'0')*1000+(str2[1]-'0')*100+(str2[2]-'0')*10+str2[3]-'0';
    int m1=(str1[5]-'0')*10+str1[6]-'0';
    int m2=(str2[5]-'0')*10+str2[6]-'0';
    int d1=(str1[8]-'0')*10+str1[9]-'0';
    int d2=(str2[8]-'0')*10+str2[9]-'0';
    int sum1=((str1[11]-'0')*10+str1[12]-'0')*60+(str1[14]-'0')*10+str1[15]-'0';//记录开始时间所对应的分钟数   
    int sum2=((str2[11]-'0')*10+str2[12]-'0')*60+(str2[14]-'0')*10+str2[15]-'0';//记录结束时间多出的分钟数  
    ll ans1=0,ans2=0;//分别用来记录前一个日期的天数和后一个日期的天数 
    int month[15]={0,31,28,31,30,31,30,31,31,30,31,30,31};
    for(int i=1;i<y1;i++)
    {
        if(i%4==0&&i%100!=0||i%400==0) ans1+=366;
        else ans1+=365;
    } 
    for(int i=1;i<m1;i++)
    {
        ans1+=month[i];
        if(i==2)
        {
            if(y1%4==0&&y1%100!=0||y1%400==0) ans1++;
        }
    }
    ans1+=1ll*d1;
     
    for(int i=1;i<y2;i++)
    {
        if(i%4==0&&i%100!=0||i%400==0) ans2+=366;
        else ans2+=365;
    } 
    for(int i=1;i<m2;i++)
    {
        ans2+=1ll*month[i]; 
        if(i==2)
        {
            if(y2%4==0&&y2%100!=0||y2%400==0) ans2++;
        }
    }
    ans2+=1ll*d2;
    //printf("%lld %lld\n",ans1,ans2);
    ans1=ans1*24*60+1ll*sum1;
    ans2=ans2*24*60+1ll*sum2;
    //printf("%lld %lld\n",ans1,ans2);
    ll tmp=ans2-ans1;
    int res=0;
    for(int i=1;i<=n;i++)
    {
        if(tmp>=s[i])
        {
            res=i;
        }
        else break;
    }
    cout<<res<<endl;
    return 0;
}

由于变量稍多,不下心就给写篡位了,导致WA了三发,心痛,qwq


--------------------------------------------------------分割线-----------------------------------------------------------------------


5. Contest2377 - 2020年春混合个人训练第二场 E: 人品指数

题目描述
队员们都到齐了,大家先入住宾馆,由于扬州是著名的旅游城市,宾馆房间很难预订,节目组预订的房间有高级的和普通的。怎样分配房间成了一个很棘手的问题,技术控李晨提出用“人品指数”来决定房间的好坏,根据往期的节目中的表现来计算人品,比如撕掉别人的名牌的人加10分,玩某个游戏得第一名加5分,第二名加3分等等。当然也可以减分,比如没有及时救助队友减10分,玩某个游戏超时减5分等等。不过,一次扣分和加分的数值不会超过100。
计算每个队员的人品指数时,每人一行。一开始的时候会给每个队员的人品指数设为100。比如李晨的信息为:lichen:100-3-5+1+2-2,则他的人品指数为:93。
到底谁能得到宾馆的最好房间呢?

输入
输入有若干行(不超过100行)。每行为一个队员的信息,其中首先是一个姓名(不超过20个字符的字符串,只含有小写字母和空格),后面是一个冒号,再后面为类似于数学的加减式(其中没有多余空格,保证合法)表示一个队员的人品加减分情况。
输出
输出人品指数最高的队员名单。如果有多个队员的人品指数一样高,请按姓名的字典顺序全部输出(一行一个姓名)。
样例输入

xiaoy:100-3-5+1+2-2
xiaox:100-10-20+1
xiaoz:100-50-50-1

样例输出

xiaoy

提示

对于100%的数据,队员的信息不超过100行。

对于本题,我觉得有两大坑点,第一,名字中带有空格;第二,一次扣分和加分的数值不会超过100。 就是这句话了,不知不觉的我就入坑了,第二个还好没进去,擦在了边缘,第一个,哎呀,小WA了几次,一开始根本没注意到,名字中有空格的情况。不过还好,最后细读一遍题给找了出来。
还有就是我认为这道题的两大难点:一、对于输入操作的处理,说实话,我在这里卡了有一会儿了;二、对于数字字符转换为整数的处理,这里没怎么卡,看出了端倪,嘿嘿。

下边我些写两种输入方式吧;
第一种:对于为什么又把字符数组转换为string类型的了呢,其实纯属个人喜好,觉得这样好操作,
STL真香,hh;

在这里插入图片描述

char test[1010];
string a;
while(gets(test))
{
	//getchar();
	a.clear();
	for(int j=0;j<strlen(test);j++)
	{
		a+=test[j];
	}
}

第二种:比较神奇啦,今天才知道还可以这样操作

while(getline(cin,a)
{
	if(a=="-1") break;
}

不多说了,其他的正常模拟就好,上代码:

#include<bits/stdc++.h>
using namespace std;
struct people{
	string name;
	int val;
}st[110];
bool cmp(people x,people y)
{
	if(x.val!=y.val) return x.val>y.val;
	else if(x.val==y.val) return x.name<y.name;
}
int qpow(int x,int y)
{
	int res=1;
	for(int i=0;i<y;i++)
	{
		res*=10;
	}
	return res;
}
int main()
{
	string a;
	char test[1010]={'\0'};
	int s=0;
	while(gets(test))
	{
		//getchar();
		a.clear();
		for(int j=0;j<strlen(test);j++)
		{
			a+=test[j];
		}
		int i;
		for(i=0;i<a.size();i++)
		{
			if(a[i]==':')
			{
				st[s].name=a.substr(0,i);
				i++;
				break;
			}
		}
		string b;
		int sum=0,num=0;
		a[a.size()]='+';
		while(a[i]>='0'&&a[i]<='9')//处理第一个数字 
		{
			b+=a[i];
			i++;
		}
		for(int j=0,k=b.size()-1;j<b.size();j++,k--)
		{
			num+=(b[j]-'0')*qpow(10,k);
		}
		sum+=num;
		b.clear();
		char type=a[i]; 
		i++;
		while(i<=a.size())
		{
			if(a[i]>='0'&&a[i]<='9')
			{
				b+=a[i];
			}
			else
			{
				num=0;
				for(int j=0,k=b.size()-1;j<b.size();j++,k--)
				{
					num+=(b[j]-'0')*qpow(10,k);
				}
				if(num>100) num=100;
				if(type=='+'){
					if(num<=100) sum+=num;
				} 
				else if(type=='-'){
					if(num<=100) sum-=num;
				} 
				b.clear();
				type=a[i];
			} 
			i++;
		}
		st[s++].val=sum;
		memset(test,'\0',sizeof(test));
	}
	sort(st,st+s,cmp);
	for(int i=0;i<s;i++)
	{
		//cout<<st[i].val<<endl;
		if(st[i].val==st[0].val)
		{
			cout<<st[i].name<<endl;
		}
		else break;
	}
	return 0;
}

由于模拟就是模拟呀,也不好怎么再分类,所以暂且就归为杂集也好,等想好其他的归类方式,在更改也很到位。

持续更新中。。。
待续。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值