纪中周末训练 2020.06.20【NOIP提高组】模拟 反思+题解

这次比赛200分,第5,比赛最后最后2分半时切掉T3,不错……

T1:【NOIP2013模拟联考5】小麦亩产一千八(kela)

Description

“有了金坷垃,肥料一袋能顶两袋撒,小麦亩产一千八,吸收两米下的氮磷钾……”,话说HYSBZ(Hengyang School for Boys & Zy)学识渊博孩纸们一讲到粮食,都会想起印度那个著名的故事:国王要在第一个格子里放入一粒小麦,接下来的格子放入前面一个格子的两倍的小麦。这样所需小麦总数是巨大的,哪是不用金坷垃就能完成的任务?不过为了减轻国王的任务,那个下棋获胜的宰相换了一个要求:“我只需要你在棋盘外放一粒小麦,可以将其理解为第0 个格子,然后你需要在第一个格子里放入p粒小麦,之后每一个格子放入前两个格子的小麦数之和的小麦,并且要满足第a 个格子放x 粒小麦,第b 个格子放……”说到这,宰相突然发现自己说的满足第a 个格子放x 粒小麦的情况可能不存在……欺君可是大罪啊!国王看到宰相迟迟不说,自己也烦了!我自己来算!于是国王拜托你,让你算出第b 个格子应该放几粒小麦。当然,就算答案不存在,你也是要告诉国王的。

Input

该题有多组数据,请读到文件末结束。

对于每一组数据仅一行,3 个正整数a,x,b,分别表示第a 个格子放了x 粒小麦,以及你所需要计算的是第b 个格子的小麦数量。

Output

对于每一次询问,仅1 个整数,为第b 个格子的小麦数量,若宰相说的情况不存在,那么请输出-1。

Sample Input

1 1 2

3 5 4

3 4 6

12 17801 19

Sample Output

2

8

-1

516847

【样例解释】

对于样例二,f[1]=2 时,能够满足f[3]=5,因此宰相没有撒谎,此时第5 个格子的小麦数应为f[4]=f[2]+f[3]=3+5=8.

Data Constraint

对于50%的数据:如果答案存在,那么p<=50

对于100%的数据:1<=数据组数<=10000,1<=a,b<=20, 数据保证如果答案存在,那么1<=p<=1000000.

反思&题解

比赛&正解思路: 找规律,题目有点像斐波那契数列,手摸一下就能发现规律……
反思: 日常签到题,淼

CODE

#include<bits/stdc++.h>
using namespace std;
long long a,x,b,f[25];
int main()
{
	long long i;
	f[0]=1;
	f[1]=1;
	for (i=2;i<=20;i++)
		f[i]=f[i-1]+f[i-2];
	while (~scanf("%lld%lld%lld",&a,&x,&b))
	{
		if (a==1)
		{
			long long l,r,k;
			l=1;
			r=x;
			k=x;
			for (i=2;i<=b;i++)
			{
				k=l+r;
				l=r;
				r=k;
			}
			printf("%lld\n",k);
			continue;
		}
		long long t;
		t=x-f[a];
		if (t%f[a-1]==0)
		{
			long long l,r,k;
			l=1;
			r=1+t/f[a-1];
			for (i=2;i<=b;i++)
			{
				k=l+r;
				l=r;
				r=k;	
			}
			printf("%lld\n",k);	
		}
		else printf("-1\n");	
			
	}
	return 0;	
}

T2:【NOIP2013模拟联考6】秀姿势(sugata)

Description

“蓝猫淘气三千问,看蓝猫,我有姿势我自豪!”话说能考上HYSBZ的孩纸们肯定都是很有姿势的孩纸们,但是大家普遍偏科,都只有一门科目考得好。已知HYSBZ的入学考试科目数量小于等于10^9,而有n个学生参加了入学考试。现在HYSBZ要刷人了,招生办每一次刷人会把一个科目考得好的人全部刷掉,但是最多不能刷超过K次。(刷就是不录取)而HYSBZ的校长看录取名单时,最喜欢看的就是连续都是同一个科目考得好的人。他定义完美学生序列为连续且考得好的科目都为同一门的学生序列。现在招生办主任想让你帮他设计一种录取方案,使得最长的完美学生连续子序列尽量长。

Input

共N+1行,第一行2个正整数n,K,n表示入学考试人数,K表示刷人次数上限。

接下来N行,每行仅一个正整数Ai,为i号学生所考得好的科目。

Output

仅1个正整数,为最长的最长完美学生连续子序列。

Sample Input

9 1

2

7

3

7

7

3

7

5

7

Sample Output

4

【样例解释】

总共有9个学生,最多只能刷一次学生。

若不刷,最长完美学生连续子序列长度为2

若刷掉考第3门考得好的学生,则学生序列变成2 7 7 7 7 5 7,最长完美学生连续子序列长度为4.

Data Constraint

对于10%的数据:n<=10

对于30%的数据:n<=1000

对于100%的数据:1<=n<=100000

反思&题解

比赛思路: 离散化加DP(乱搞一通)
正解思路: 队列处理区间(其实看了题解之后觉得特水),还可以用hash或者离散化 (本蒟蒻太菜,还没码)
反思: 考试的思路不能太局限,不然简单的题目容易想难了

CODE

#include<bits/stdc++.h>
using namespace std;
int n,k,ans;
queue<int>d;
map<int,int>sum;
int main()
{
	scanf("%d%d",&n,&k);
	int i,x,tot;
	tot=0;
	for (i=1;i<=n;i++)
	{
		scanf("%d",&x);
		if (!sum[x])
		{
			tot++;
			while (tot>k+1)
			{
				int t=d.front();
				sum[t]--;
				if (!sum[t]) tot--;
				d.pop();	
			}
				
		}
		sum[x]++;
		d.push(x);
		if (sum[x]>ans) ans=sum[x];
	}
	printf("%d\n",ans);
	return 0;
}

T3:【NOIP2013模拟联考5】休息(rest)

Description

休息的时候,可以放松放松浑身的肌肉,打扫打扫卫生,感觉很舒服。在某一天,某LMZ 开始整理他那书架。已知他的书有n 本,从左到右按顺序排列。他想把书从矮到高排好序,而每一本书都有一个独一无二的高度Hi。他排序的方法是:每一次将所有的书划分为尽量少的连续部分,使得每一部分的书的高度都是单调下降,然后将其中所有不少于2 本书的区间全部翻转。重复执行以上操作,最后使得书的高度全部单调上升。可是毕竟是休息时间,LMZ 不想花太多时间在给书排序这种事上面。因此他划分并翻转完第一次书之后,他想计算,他一共执行了多少次翻转操作才能把所有的书排好序。LMZ 惊奇地发现,第一次排序之前,他第一次划分出来的所有区间的长度都是偶数。

Input

第一行一个正整数n, 为书的总数。

接下来一行n个数,第i个正整数Hi,为第i 本书的高度。

Output

仅一个整数,为LMZ 需要做的翻转操作的次数。

Sample Input

6

5 3 2 1 6 4

Sample Output

3

【样例解释】

第一次划分之后,翻转(5,3,2,1),(6,4)。之后,书的高度为1 2 3 5 4 6,然后便是翻转(5,4)即可。

Data Constraint

对于10%的数据:n<=50

对于40%的数据:n<=3000

对于100%的数据:1<=n<=100000, 1<=Hi<=n

反思&题解

比赛&正解思路: 先把所有的降序子序列全部翻转,之后求一下逆序对,结果相加就行 (结论我是手摸出来的)
下面给出官方解释:
在找出所有的单调下降序列并翻转后,可以发现,刚刚找到的区间内的元素都已经变得有序。
也就是说,只有两个小区间之间的数可以进行交换。
显然,我们只会交换两个降序的数。即逆序对。
因此答案为逆序对数与翻转次数之和。

反思: 要多从其他角度切入问题

CODE

#include<bits/stdc++.h>
using namespace std;
int a[100005],b[100005],n,c[100005];
long long ans;
void gb(int i,int j)
{
	int l,r,mid,k;
	
	if (i==j) return;
	mid=(i+j)>>1;
	gb(i,mid);
	gb(mid+1,j); 
	l=i;
    r=mid+1;
    k=i;
    while (l<=mid && r<=j)
    {
        if (a[l]<=a[r])
        {
        	b[k]=a[l];
            l++;
            k++;
		}
        else
        {
        	ans+=mid-l+1;
            b[k]=a[r];
            r++;
            k++;
		}
	}
    while (l<=mid)
    {
    	b[k]=a[l];
        l++;
        k++;
	}
    while (r<=j)
    {
    	b[k]=a[r];
        r++;
        k++;
	}
    for (k=i;k<=j;k++)
            a[k]=b[k];
}
int main()
{
	scanf("%d",&n);
	int i;
	for (i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		c[i]=a[i];
	}
	a[n+1]=0x3f3f3f3f;
	int l;
	l=1;
	ans=0;
	for (i=1;i<=n;i++)
	{
		if (a[i]<a[i+1])
		{
			int j;
			for (j=l;j<=i;j++)
				a[j]=c[i-j+l];
			l=i+1;
			ans++;	
		}
	}
	gb(1,n);
	printf("%lld\n",ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/CMC_YXY/article/details/106873596
今日推荐