2013年福建省程序设计热身赛

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

A. Easy Problem

       这题是special judge,即答案不唯一的题。题意是输入一个大于4的正整数N,然后让你输出3个比N小的数。一种解法是不管N,全部输出1 2 3。

       举办方出这题是为了提醒我们明日的正赛会有这样的special judge题。

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

B. Number lengths (FOJ1050)

       题意:输入N,输出N的阶乘是几位数。

       思路:用以10为底的对数运算,能计算一个数是几位数(好好思考为什么)。而对数内部的乘法,可以拆开变成加法运算。(以下代码用GNU C++提交)

#include <cstdio>
#include <cmath>
using namespace std;

int main() {
	int n;
	while (scanf("%d", &n) != EOF) {
		double ans = 1; 
		for (int i = 2; i <= n; i++) ans += log10(i);
		printf("%d\n", int(ans));
	}
	return 0;
}

       这样的代码已经能AC了,不过用时78ms。看到有人0ms AC,说明还是能再优化的。见斯特林公式。公式两边同取对数,注意代码中对公式的稍许变化,避免了sqrt运算和提高运算精度。

#include <cstdio>
#include <cmath>
using namespace std;
const double PI = atan(1.0)*4;

int main() {
	int n;
	while (scanf("%d", &n) != EOF) {
		int ans = (int)((n*log(n)-n+0.5*log(2*n*PI))/log(10.0))+1;
		printf("%d\n", ans);
	}
	return 0;
}
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
C. 土地划分( FOJ1015)

       题意:在一个矩形土地里用L条线段划分,问能划分出多少块土地。

       思路:首先要推导出土地数只跟矩形内的交点个数有关。想想看,L条线段如果互不相交(端点相交不算,以下均如此计算),则可以划分出L+1块土地。又线段间每产生一个交点,就多划分出一份土地。所以土地总数就是L+1+交点数。

       故接下来的难点是如何通过两个线段的端点(点a1,点a2,点b1,点b2),来判断线段a与b是否相交。这里可以用快速排斥和跨立实验。更简单的,不用管那么多原理,计算几何题本来就需要经常套用模板求解,在大白书(刘汝佳的《算法竞赛入门经典——训练指南》第4章),有很多优秀的模板,包括判断两线段是否“规范相交”的SegmentProperIntersection函数。下面的代码从第4至第19行是相应的计算几何模板(实际刷题都是整套模板贴的,模板很长,这里为了简洁,只留下必须的内容),故主函数非常简单,只要每得到一个新的线段,就跟之前的所有线段比较,累加相交次数即可。

#include <iostream>
#include <cmath>
using namespace std;
const double eps = 1e-10;
int dcmp(double x) {if(fabs(x)<eps) return 0; else return x<0?-1:1;}

struct Point{
	double x, y;
	Point(double a=0, double b=0):x(a),y(b) { }
};
typedef Point Vector;
Vector operator - (Point A, Point B) { return Vector(A.x-B.x, A.y-B.y); }
double Cross(Vector A, Vector B) { return A.x*B.y-A.y*B.x; }

bool SegmentProperIntersection(Point a1, Point a2, Point b1, Point b2) {
	double c1 = Cross(a2-a1,b1-a1), c2 = Cross(a2-a1,b2-a1),
		   c3 = Cross(b2-b1,a1-b1), c4 = Cross(b2-b1,a2-b1);
	return dcmp(c1)*dcmp(c2)<0 && dcmp(c3)*dcmp(c4)<0;
}

int main() {	
	Point P[60];
	int w, h, L, i, j, ans;
	
	while (cin >> w >> h, w&&h) {
		cin >> L >> P[0].x >> P[0].y;
		ans = L+1;
		for (i = 1; i <= L; i++) {
			cin >> P[i].x >> P[i].y;
			for (j = 1; j < i; j++) {
				ans += SegmentProperIntersection(P[j-1],P[j],P[i-1],P[i]);
			}
		}
		cout << ans << endl;
	}
	return 0;
}
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

D. Key problem(FOJ1692)
       这题我之前的一篇博客整理的很好很详细了:FOJ 1692 Key problem


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值