2018清北学堂普及组冲刺班6连考总结反思

DAY 1
Problem 1 A(A.cpp/c/pas)
【题目描述】
给出一个n*m的网格,其中小明初始站在(x,y)这个位置,网格内无障碍,小明可以向上下左右四个方向一步走一格,问小明最少走几步可以走出网格。
【输入格式】
输入文件A .in
第一行四个整数n,m,x,y。
【输出格式】
输出文件A.out
一行一个整数表示答案。
【样例输入】
3 3 2 2
【样例输出】
2
【数据范围】
对于 30% 数据 n,m<=3
对于 50% 数据 n,m<=1000
对于 100% 数据 n,m<=1000000000,1<=x<=n,1<=y<=m;

想法很简单的一道题目,但是我想多了,广搜也会超时呀!!!

源代码

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

int dx[5]={0,0,-1,0,1};        
int dy[5]={0,-1,0,1,0};

struct node
{
	long x;
	long y;
	long ans;
}p,q;

long start_x,start_y,n,m;

int main()
{
	freopen("A.in","r",stdin);
	freopen("A.out","w",stdout);
	
	cin>>n>>m>>start_x>>start_y;
	
	if (start_x < 1 || start_y < 1 || start_x > n || start_y > m)
		{
			cout<<0;
			
			return 0;
		}

	queue <node> line;
	p.x = start_x;
	p.y = start_y;
	p.ans = 0;
	line.push(p);
	
	while (!line.empty())
		{
			p = line.front();
			
		//	if (p.x == n && p.y == m)
		//		{
		//			cout<<p.ans;
					
		//			break;
		//		}
			
			p.ans++;
			
			for (int i = 1; i <= 4; i++)
				{
					q = p;
					int xx = p.x + dx[i];
					int yy = p.y + dy[i];
					q.x = xx;
					q.y = yy;
					
					if (xx < 1 || xx > n || yy < 1 || yy > m) 
						{
							cout<<p.ans<<endl;
							
							return 0;
						}
					
					line.push(q);
				}
		
			line.pop();
		}
}
//50分qoq

我还是搜索写上头了QAQ
std

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

int n,m,x,y,ans1,ans2; 

int main()
{
	cin>>n>>m>>x>>y;
	//我也想到直接判断直线距离了呀   哎。。。可惜
	ans1 = min(x,abs(x-n));
	ans2 = min(y,abs(y-m));
	
	cout<<min(ans1,ans2)+1;
	
	return 0;
}
//当时只想装一下b,然后就没有然后了

反思要注意审题,对合适的题型使用合适的算法,不要再犯这样坑爹的低级错误了

Problem 2 B(B.cpp/c/pas)
【题目描述】
Lucy家门前的大街上有n家店,lucy是一个喜欢收藏机械键盘的女孩子,这n家店中第i家店卖的键盘价格为V[i],lucy前前后后有q天心血来潮买电脑,其中第i次买电脑的预算是K[i],问每一次有多少店的键盘能供lucy选择,能选择当且仅当该店的键盘价格小于等于lucy的预算。
【输入格式】
输入文件B.in
输入文件第一行两个整数n,q。
接下来一行n个整数,其中第i个整数为V[i]。
第q行每行一个整数K代表该次买电脑的预算。
【输出格式】
输出文件B.out。
输出文件q行,第i行表示第i次买电脑,能有多少家店可供选择。
【样例输入】
6 3
6 5 4 3 2 1
1
3
5
【样例输出】
1
3
5
【数据范围】
对于30%的数据,n,q<=1000。
对于另外30%的数据,n,q<=100000,0<=V[i],K[i]<=100000
对于100%的数据,
n<=100000,m<=100000,0<=V[i],K[i]<=10^9。

想法自己上来就写了,没看清数据范围QAQ(看清了也写不来 ) 这题是二分呀!!!

源代码

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

long a[100009],n,q,k,b[100009];
long total;

int main()
{
	freopen("B.in","r",stdin);
	freopen("B.out","w",stdout);
	
	cin>>n>>q;
	if (n == 0) 
		{
			for (int i = 1; i <= q; i++)
				cout<<0<<endl;
				
			return 0;
		}
		
	for (int i = 1; i <= n; i++)
		cin>>a[i];
		
	sort(a+1,a+n+1);
		
	for (int i = 1; i <= q; i++)
		cin>>b[i];
		
	for (int i = 1; i <= q; i++)
		{
			total = 0;
			
			for (int j = 1; j <= n; j++)
				if (b[i] >= a[j]) total++;
					else
						break;
			
			cout<<total<<endl;	
		}	
	return 0;
}
//30分(楼下风景不错,马上下去,快上天台了)

std

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

int n,q,k;
int a[100009];

int main()
{
	cin>>n>>q;
	
	for (int i = 1; i <= n; i++)
		cin>>a[i];
		
	sort(a+1,a+n+1);
	
	for (int i = 1; i <= q; i++)
		{
			cin>>k;
			
			int p = upper_bound(a+1,a+n+1,k)-a;     //二分函数,找到大于的返回
			
			cout<<k<<endl;
		}
		
	return 0;
}

反思要注意看范围 要注意看范围 要注意看范围(重要的事情说3遍 ),要加强对二分的练习

Problem 3 C(C.cpp/c/pas)
【题目描述】
有一个无限范围的蜂窝状的网格,小明决定在这个网格中探险。
我们看一下这一张图,来看整个网格的坐标结构。

在这里插入图片描述
小明从(0,0)点出发,按照旋涡状移动(见下图),求移动n步后,小明所处的坐标。
在这里插入图片描述
【输入格式】
输入文件C.in
输入一行一个整数n。
【输出格式】
输出文件C.out
输出一行两个整数x,y表示小明n步之后所处的坐标。
【样例输入1】
3
【样例输出1】
-2 0
【样例输入2】
7
【样例输出2】
3 2
【数据范围】
对于30%的数据,n<=30;
对于50%的数据,n<=500;
对于100%的数据,n<=10^18;

std:

#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int up=577350270;

ll n,rest,x,y;

int main()
{
	freopen("C.in","r",stdin);
	freopen("C.out","w",stdout);

	scanf("%I64d",&n);
	if (n==0) {printf("0 0");return 0;}
	
	int l=1,r=up,mid,ans;
	while (l<=r)
	{
		mid=(l+r)>>1;
		if (3ll*mid*(mid+1)>=n) ans=mid,r=mid-1;else l=mid+1;
	}
	rest=n-3ll*ans*(ans-1);rest--;
	x=ans*2-1,y=2;
	
	if (rest<ans) 
	{
		x-=rest;
		y+=2*rest;
	}
	else 
	{
		x-=ans-1;
		y+=2*(ans-1);
		rest-=ans-1;
		if (rest<=ans) x-=2*rest;
		else 
		{
			x-=ans*2;
			rest-=ans;
			if (rest<=ans) 
			{
				x-=rest;
				y-=2*rest;
			}
			else 
			{
				x-=ans;
				y-=2*ans;
				rest-=ans;
				if (rest<=ans) 
				{
					x+=rest;
					y-=2*rest;
				}
				else 
				{
					x+=ans;
					y-=2*ans;
					rest-=ans;
					if (rest<=ans) x+=2*rest;
					else 
					{
						x+=2*ans;
						rest-=ans;

						x+=rest;
						y+=2*rest;
					}	
				}
			}
		}
	}
	printf("%I64d %I64d",x,y);
	return 0;
}
//dalao代码,没啥想说的

2018.10.1

DAY 2
Problem 1 A(A.cpp/c/pas)
【题目描述】
初始有n个包子,第i个包子的大小为a[i],我们要把所有包子放在蒸笼里蒸熟。由于强迫症的原因,对于每一笼包子,包子的大小必须是相同的,在这个问题中我们假设一个蒸笼是无限大的,也就是可以放任意多个包子。
我们现在想知道,如何把给包子安排对应的蒸笼,使得蒸笼的数量最少。输出最少的蒸笼的数量,以及含包子最多的蒸笼的包子数量是多少。
【输入格式】
输入文件A.in
第一行一个整数n。
第二行n个整数,其中第i个整数a[i]表示第i个包子的大小。
【输出格式】
输出文件A.out
一行两个整数分别表示最优方案下,包子最多的蒸笼的包子数量和最少蒸笼数量。
【样例输入1】
3
1 2 3
【样例输出1】
1 3
【样例输入2】
4
6 5 6 7
【样例输出2】
2 3
【数据范围】
对于 30% 数据 n,a[i]<=1000
对于 50% 数据 n<=100000,a[i]<=1000
对于 100% 数据 n,m<=100000,a[i]<=10^9

想法长了上一次的教训,这次乖乖的写线性的算法了(拜拜二重for,拿走拿走不客气 ),觉得可以用队列的维护来写

源代码

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

long a[100009],i,k,sum,total,n;

int main()
{
	freopen("A.in","r",stdin);
	freopen("A.out","w",stdout);
	
	queue <long> line;
	
	cin>>n;
	for (i = 1; i <= n; i++)
		cin>>a[i];
		
	sort(a+1,a+n+1);
	
	i = 1;
	k = 1;
	sum = 1;
	total = 1;
	line.push(a[i]);
	
	while (i < n)      //维护队列,线性算法
		{
			i++;
			
			if (a[i] != line.front())
				{
					total = max(total,sum);
					k++;
					line.pop();
					line.push(a[i]);
					sum = 1;
				}	
				else
					sum++;
		}
	
	total = max(total,sum);
	
	cout<<total<<' '<<k;
	
	return 0;
}
//不A了这一题,天理难容呀

std

#include<stdio.h>
#include<set>
#include<map>
#include<algorithm>
using namespace std;

int n,s[101000];
map<int,int>ff;
set<int>ss;

int main()
{
	freopen("A.in","r",stdin);
	freopen("A.out","w",stdout); 
    scanf("%d",&n);

    for(int i=0;i<n;i++)
    {
        scanf("%d",&s[i]);
        ff[s[i]]++;
        ss.insert(s[i]);
    }

    int ma=0;

    for(int i=0;i<n;i++)
        ma=max(ma,ff[s[i]]);
    
    printf("%d %d\n",ma,ss.size());
    return 0;
//大佬用map写的
}

反思多多注意对时间复杂度的减少,尽力写最优的算法

Problem 2 B(B.cpp/c/pas)
【题目描述】
定义n!为123……*n。
我们求现在要求(0!+1!+2!……+n!)对m取模的结果。
(提示:数学上定义0!为1。)
【输入格式】
输入文件B.in
第一行两个整数n,m。
【输出格式】
输出文件B.out
【样例输入】
4 100
【样例输出】
34
【数据范围】
对于30%的数据,n<=1000000
对于50%的数据,n<=10^9
对于100%的数据,n<=10^100,m<=1000000

想法第一感觉高精度,然后就一口气写到底,然后。。。。。美妙的。。。。爆零了 QAQ ~~mmp我写了两个小时呀~~

源代码

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

int a[40002]={0,1},s[40002]={0};
int i,n,alen=1,j,slen=1,k,l=1,v=1,m;
	
int main()
{
	freopen("B.in","r",stdin);
	freopen("B.out","w",stdout);
	
	cin>>n>>m;
	
	s[1] = 1;

	for(k = 1; k <= n; k++)        //算阶乘和
		{
			for(j = 1; j <= alen; j++)
				a[j] *= l;
				
			for(j = 1; j <= alen; j++)
				if(a[j] >= 10)
					{
						a[j+1] += a[j] / 10;
						a[j] %= 10;
						v++;
					}
				
			alen++;
			
			while(a[alen] >= 10)
				{
					a[alen+1] = a[alen] / 10;
					a[alen] %= 10;
					alen++;
					v++;
				}
				
			l++;
			
			slen=max(slen,alen);
		
			for(i = 1; i <= slen; i++)
			{
				s[i] += a[i];
				
				if(s[i] >= 10)
					{
						if(i == slen) slen++;
						s[i] %= 10;
						s[i+1]++;
					}
			}
		
			alen=v;
		}
		
	for(i = slen; i >= 1; i--)
			if(s[i] == 0 && slen > 1) slen--;
				
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值