(2018.1.25上午【纪雅零基础 NOIP2007 】模拟赛)

本文解析了NOIP2007四道编程题的解题思路及代码实现,包括奖学金分配、纪念品分组、守望者逃离与Hanoi双塔问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天花了些时间完成这些题。(虽然都很水)

JZOJ NO.1【NOIP2007】奖学金

代码如下

#include <cstdio>
#include <algorithm>
using namespace std;
struct z{int c,m,e,s,u;}a[301]; int n;
bool cmp(z x,z y){
  if (x.s!=y.s) return x.s>y.s;
  if (x.c!=y.c) return x.c>y.c;
  return x.u<y.u;
}
int main(){
	freopen("scholar.in","r",stdin);
	freopen("scholar.out","w",stdout);
	scanf("%d",&n);
	for (int i=1;i<=n;i++) 
	scanf("%d%d%d",&a[i].c,&a[i].m,&a[i].e),a[i].u=i,a[i].s=a[i].c+a[i].m+a[i].e;
	sort(a+1,a+1+n,cmp);
	for (int i=1;i<=5;i++) printf("%d %d\n",a[i].u,a[i].s);
	return 0;
}

JZOJ NO.2 【NOIP2007】纪念品分组

思路:

挑两个,也就是说一大一小,如果分不了,大的自成一家,小的继续匹配。(先排序)


代码

#include <cstdio>
using namespace std;
int b[201],a[30001],n,m,k,x;
int main(){
	freopen("group.in","r",stdin);
	freopen("group.out","w",stdout);
	scanf("%d%d",&m,&k);
	for (int i=1;i<=k;i++) scanf("%d",&x),b[x]++;
	for (int i=1;i<=200;i++)
	for (int j=1;j<=b[i];j++) a[++n]=i;
	int l=1,r=n;
	while (l<r){
		if (a[l]+a[r]<=m) l++,r--,n--;
		else r--;
	}
	printf("%d",n);
	return 0;
}

JZOJ NO.3 【NOIP2007】守望者的逃离

思路:

对于每一秒,有三种操作,法术,恢复,跑步。
每一秒算出最优方案,到达直接退出,超时game over


代码

#include <cstdio>
using namespace std;
int x,y,m,s,t;
int main(){
	freopen("escape.in","r",stdin);
	freopen("escape.out","w",stdout);
	scanf("%d%d%d",&m,&s,&t);
	for (int i=1;i<=t;i++){
		x+=17;//跑步(和法术分开的)
		if (m>=10){y+=60;m-=10;}//法术
		else m+=4;//恢复
		if (x<y) x=y;//最优(这里才求最优)
		if (x>=s){
			printf("Yes\n%d",i);
			return 0;
		}
	}
	printf("No\n%d",x);
	return 0;
}

JZOJ NO.4【NOIP2007】Hanoi双塔问题

思路:

通过找规律可以发现=2∗(2n−1)=2n+1−22*(2^n -1)=2^{n+1}-22(2n1)=2n+12
所以就是高精度了,这里我把数拆开了。
176176176 输出2177−2=(225)7×22−22^{177}-2=(2^{25})^7\times 2^2-221772=2257×222


代码

#include <cstdio>
using namespace std;
const int maxn=1000;
int a[maxn+1],n,s;
void times(int s){
	for (int i=maxn;i>=1;i--) a[i]*=s;
	for (int i=maxn;i>=1;i--) a[i-1]+=a[i]/10,a[i]%=10;
}
void print(){
	int j=1;
	while (j<maxn&&!a[j]) j++;
	for (int i=j;i<=maxn;i++) putchar(a[i]+48);
}
int main(){
	freopen("hanoi.in","r",stdin);
	freopen("hanoi.out","w",stdout);
	scanf("%d",&n); n++;
	s=1<<(n%25); a[maxn]=1;
	for (int i=0;i<=n/25;i++) times(s),s=33554432; a[maxn]-=2;
	print(); return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值