文章目录
icpc2013长沙区域赛
A.Alice’s Print Service
题意: 现在你要打印一些东西,比如需要99张纸,打印100张以下时话费10元每张,100张及100张以上时需要5元每张,此时你可以选择打印100张,使得花费更小。现给一个数字n,表示n个区间段,然后有s1,p1,s2,p2…sn,pn,表示打印纸张大于等于s1而小于s2时,每张纸话费p1元,现有m个询问,问每次给你x张纸,所需的最小花费是多少。
题解: 先倒着 O ( n ) O(n) O(n)预处理一遍打印多少纸张的最小划分是多少,然后每次询问二分去找答案即可
代码:
#include <bits/stdc++.h>
using namespace std;
#define MAXN 100100
long long s[MAXN], p[MAXN];
long long minm[MAXN];
int main() {
long long n, m, i, j;
long long t;
long long x, ans;
scanf("%lld", &t);
while (t--) {
scanf("%lld%lld", &n, &m);
for (i = 0; i < n; i++) {
scanf("%lld%lld", &s[i], &p[i]);
}
minm[n - 1] = s[n - 1] * p[n - 1];
for (i = n - 2; i >= 0; i--) {
long long tt = s[i] * p[i];
minm[i] = min(tt, minm[i + 1]);
}
for (i = 0; i < m; i++) {
scanf("%lld", &x);
int pp = upper_bound(s, s + n, x) - s;
pp--;
if (pp == n - 1) {
ans = x * p[n - 1];
} else
ans = min(minm[pp + 1], x * p[pp]);
printf("%lld\n", ans);
}
}
return 0;
}
C.Collision
题意: 给出一个半径为R的大圆,这个圆里面有一个同心圆model,现在向这个model发射一枚硬币(给出速度vx,vy),碰到model会反射,问硬币在大圆内运行的时间(保证硬币的初始位置在圆外)
题解: 首先判断是否是向大圆方向射去,也就是点到圆心的向量和速度向量的夹角是否小于90度,不小于90度则肯定不会相交,判断夹角小于90度可以用点积大于0来求。然后判断运行轨迹是否能碰到model,这里用点到直线距离来求即可,如果原点到直线的距离小于等于r+Rm,那么肯定不反射,直接利用勾股定理求时长即可。最后是反射的情况:
利用两次勾股定理算出x,因为是对称的,直接乘2即可
代码:
#include <bits/stdc++.h>
using namespace std;
// 计算几何模板
const double eps = 1e-8;
const double inf = 1e20;
const double pi = acos(-1.0);
const int maxp = 1010;
// 和0做比较
int sgn(double x) {
if (fabs(x) < eps) return 0; // =0
if (x < 0)
return -1; // < 0
else
return 1; // > 0
}
// 计算x的平方
inline double sqr(double x) {
return x * x; }
struct Point {
double x, y;
Point() {
}
Point(double _x, double _y) {
x = _x;
y = _y;
}
void input() {
scanf("%lf%lf", &x, &y); }
void output() {
printf("%.2f %.2f\n", x, y); }
bool operator==(Point b) const {
return sgn(x - b.x) == 0 && sgn(y - b.y) == 0;
}
bool operator<(Point b) const {
return sgn(x - b.x) == 0 ? sgn(y - b.y) < 0 : x < b.x;
}
Point operator-(const Point &b) const {
return Point(x - b.x, y - b.y); }
//叉积
double operator^(const Point &b) const {
return x * b.y - y * b.x; }
//点积
double operator*(const Point &b) const {
return x * b.x + y * b.y; }
//返回向量长度
double len() {
// hypot(x, y), 即sqrt(x * x + y * y)
return hypot(x, y); //库函数
}
//返回长度的平方
double len2() {
return x * x + y * y; }
//返回两点的距离
double dist(Point p) {
return hypot(x - p.x, y - p.y); }
Point operator+(const Point &b) const {
return Point(x + b.x, y + b.y); }
Point operator*(const double &k) const {
return Point(x * k, y * k); }
Point operator/(const double &k) const {
return Point(x / k, y / k); }
}