2019西北工业大学程序设计创新实践基地春季选拔赛(重现赛)

A Chino with Geometry <计算几何>

懒省事直接贴kuangbin大大的模版了。。最后取整加了个精度损失

#include 
#include 
#define fst first
#define sed second
using namespace std;
typedef long long ll;

const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
// 计算几何模板
const double eps = 1e-8;
const double inf = 1e20;
const double pi = acos(-1.0);
const int maxp = 1010;
//Compares a double to zero
int sgn(double x){
	if (fabs(x) < eps)return 0;
	if (x < 0)return-1;
	else return 1;
}
//square of a double
inline double sqr(double x){ return x*x; }
/*
* Point
* Point()-Empty constructor
* Point(double _x,double _y)-constructor
* input()-double input
* output()-%.2f output
* operator ==-compares x and y
* operator <-compares first by x, then by y
* operator-? return new Point after subtracting
curresponging x and y
* operator ^-cross product of 2d points
* operator *-dot product
* len()-gives length from origin
* len2()-gives square of length from origin
* distance(Point p)-gives distance from p
* operator + Point b-returns new Point after adding
curresponging x and y
* operator * double k-returns new Point after multiplieing x and
y by k
* operator / double k-returns new Point after divideing x and y
by k
* rad(Point a,Point b)-returns the angle of Point a and Point b
from this Point
* trunc(double r)-return Point that if truncated the
distance from center to r
* rotleft()-returns 90 degree ccw rotated point
* rotright()-returns 90 degree cw rotated point
* rotate(Point p,double angle)-returns Point after rotateing the
Point centering at p by angle radian ccw
*/
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(){
		return hypot(x, y);//库函数
	}
	//返回长度的平方
	double len2(){
		return x*x + y*y;
	}
	//返回两点的距离
	double distance(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);
	}
	//计算 pa 和 pb 的夹角
	//就是求这个点看 a,b 所成的夹角
	//测试 LightOJ1203
	double rad(Point a, Point b){
		Point p = *this;
		return fabs(atan2(fabs((a - p) ^ (b - p)), (a - p)*(b - p)));
	}
	//化为长度为 r 的向量
	Point trunc(double r){
		double l = len();
		if (!sgn(l))return *this;
		r /= l;
		return Point(x*r, y*r);
	}
	//逆时针旋转 90 度
	Point rotleft(){
		return Point(-y, x);
	}
	//顺时针旋转 90 度
	Point rotright(){
		return Point(y, -x);
	}
	//绕着 p 点逆时针旋转 angle
	Point rotate(Point p, double angle){
		Point v = (*this) - p;
		double c = cos(angle), s = sin(angle);
		return Point(p.x + v.x*c - v.y*s, p.y + v.x*s + v.y*c);
	}
};
/*
* Stores two points
* Line()-Empty constructor
* Line(Point _s,Point _e)-Line through _s and _e
* operator ==-checks if two points are same
* Line(Point p,double angle)-one end p , another end at
angle degree
* Line(double a,double b,double c)-Line of equation ax + by + c
= 0
* input()-inputs s and e
* adjust()-orders in such a way that s < e
* length()-distance of se
* angle()-return 0 <= angle < pi
* relation(Point p)-3 if point is on line
* 1 if point on the left of line
* 2 if point on the right of line
* pointonseg(double p)-return true if point on segment
* parallel(Line v)-return true if they are
parallel
* segcrossseg(Line v)-returns 0 if does not intersect
* returns 1 if non-standard
intersection
* returns 2 if intersects
* linecrossseg(Line v)-line and seg
* linecrossline(Line v)-0 if parallel
* 1 if coincides
* 2 if intersects
* crosspoint(Line v)-returns intersection point
* dispointtoline(Point p)-distance from point p to the
line
* dispointtoseg(Point p)-distance from p to the segment
* dissegtoseg(Line v)-distance of two segment
* lineprog(Point p)-returns projected point p on se
line
* symmetrypoint(Point p)-returns reflection point of p
over se
*
*/
struct Line{
	Point s, e;
	Line(){}
	Line(Point _s, Point _e){
		s = _s;
		e = _e;
	}
	bool operator ==(Line v){
		return (s == v.s) && (e == v.e);
	}
	//根据一个点和倾斜角 angle 确定直线,0<=angle
	Line(Point p, double angle){
		s = p;
		if (sgn(angle - pi / 2) == 0){
			e = (s + Point(0, 1));
		}
		else{
			e = (s + Point(1, tan(angle)));
		}
	}
	//ax+by+c=0
	Line(double a, double b, double c){
		if (sgn(a) == 0){
			s = Point(0, -c / b);
			e = Point(1, -c / b);
		}
		else if (sgn(b) == 0){
			s = Point(-c / a, 0);
			e = Point(-c / a, 1);
		}
		else{
			s = Point(0, -c / b);
			e = Point(1, (-c - a) / b);
		}
	}
	void input(){
		s.input();
		e.input();
	}
	void adjust(){
		if (e < s)swap(s, e);
	}
	//求线段长度
	double length(){
		return s.distance(e);
	}
	//返回直线倾斜角 0<=angle
	double angle(){
		double k = atan2(e.y - s.y, e.x - s.x);
		if (sgn(k) < 0)k += pi;
		if (sgn(k - pi) == 0)k -= pi;
		return k;
	}
	//点和直线关系
	//1 在左侧
	//2 在右侧
	//3 在直线上
	int relation(Point p){
		int c = sgn((p - s) ^ (e - s));
		if (c < 0)return 1;
		else if (c > 0)return 2;
		else return 3;
	}
	// 点在线段上的判断
	bool pointonseg(Point p){
		return sgn((p - s) ^ (e - s)) == 0 && sgn((p - s)*(p - e)) <= 0;
	}
	//两向量平行 (对应直线平行或重合)
	bool parallel(Line v){
		return sgn((e - s) ^ (v.e - v.s)) == 0;
	}
	//两线段相交判断
	//2 规范相交
	//1 非规范相交
	//0 不相交
	int segcrossseg(Line v){
		int d1 = sgn((e - s) ^ (v.s - s));
		int d2 = sgn((e - s) ^ (v.e - s));
		int d3 = sgn((v.e - v.s) ^ (s - v.s));
		int d4 = sgn((v.e - v.s) ^ (e - v.s));
		if ((d1^d2) == -2 && (d3^d4) == -2)return 2;
		return (d1 == 0 && sgn((v.s - s)*(v.s - e)) <= 0) ||
			(d2 == 0 && sgn((v.e - s)*(v.e - e)) <= 0) ||
			(d3 == 0 && sgn((s - v.s)*(s - v.e)) <= 0) ||
			(d4 == 0 && sgn((e - v.s)*(e - v.e)) <= 0);
	}
	//直线和线段相交判断
	//-*this line -v seg
	//2 规范相交
	//1 非规范相交
	//0 不相交
	int linecrossseg(Line v){
		int d1 = sgn((e - s) ^ (v.s - s));
		int d2 = sgn((e - s) ^ (v.e - s));
		if ((d1^d2) == -2) return 2;
		return (d1 == 0 || d2 == 0);
	}
	//两直线关系
	//0 平行
	//1 重合
	//2 相交
	int linecrossline(Line v){
		if ((*this).parallel(v))
			return v.relation(s) == 3;
		return 2;
	}
	//求两直线的交点
	//要保证两直线不平行或重合
	Point crosspoint(Line v){
		double a1 = (v.e - v.s) ^ (s - v.s);
		double a2 = (v.e - v.s) ^ (e - v.s);
		return Point((s.x*a2 - e.x*a1) / (a2 - a1), (s.y*a2 - e.y*a1) / (a2 - a1
			));
	}
	//点到直线的距离
	double dispointtoline(Point p){
		return fabs((p - s) ^ (e - s)) / length();
	}
	//点到线段的距离
	double dispointtoseg(Point p){
		if (sgn((p - s)*(e - s)) < 0 || sgn((p - e)*(s - e)) < 0)
			return min(p.distance(s), p.distance(e));
		return dispointtoline(p);
	}
	//返回线段到线段的距离
	//前提是两线段不相交,相交距离就是 0 了
	double dissegtoseg(Line v){
		return min(min(dispointtoseg(v.s), dispointtoseg(v.e)), min(v
			.dispointtoseg(s), v.dispointtoseg(e)));
	}
	//返回点 p 在直线上的投影
	Point lineprog(Point p){
		return s + (((e - s)*((e - s)*(p - s))) / ((e - s).len2()));
	}
	//返回点 p 关于直线的对称点
	Point symmetrypoint(Point p){
		Point q = lineprog(p);
		return Point(2 * q.x - p.x, 2 * q.y - p.y);
	}
};
//圆
struct circle{
	Point p;//圆心
	double r;//半径
	circle(){}
	circle(Point _p, double _r){
		p = _p;
		r = _r;
	}
	circle(double x, double y, double _r){
		p = Point(x, y);
		r = _r;
	}
	//三角形的外接圆
	//需要 Point 的 + / rotate() 以及 Line 的 crosspoint()
	//利用两条边的中垂线得到圆心
	//测试:UVA12304
	circle(Point a, Point b, Point c){
		Line u = Line((a + b) / 2, ((a + b) / 2) + ((b - a).rotleft()));
		Line v = Line((b + c) / 2, ((b + c) / 2) + ((c - b).rotleft()));
		p = u.crosspoint(v);
		r = p.distance(a);
	}
	//三角形的内切圆
	//参数 bool t 没有作用,只是为了和上面外接圆函数区别
	//测试:UVA12304
	circle(Point a, Point b, Point c, bool t){
		Line u, v;
		double m = atan2(b.y - a.y, b.x - a.x), n = atan2(c.y - a.y, c.x - a.
			x);
		u.s = a;
		u.e = u.s + Point(cos((n + m) / 2), sin((n + m) / 2));
		v.s = b;
		m = atan2(a.y - b.y, a.x - b.x), n = atan2(c.y - b.y, c.x - b.x);
		v.e = v.s + Point(cos((n + m) / 2), sin((n + m) / 2));
		p = u.crosspoint(v);
		r = Line(a, b).dispointtoseg(p);
	}
	//输入
	void input(){
		p.input();
		scanf("%lf", &r);
	}
	//输出
	void output(){
		printf("%.2lf?%.2lf?%.2lf\n", p.x, p.y, r);
	}
	bool operator == (circle v){
		return (p == v.p) && sgn(r - v.r) == 0;
	}
	bool operator < (circle v)const{
		return ((p < v.p) || ((p == v.p) && sgn(r - v.r) < 0));
	}
	//面积
	double area(){
		return pi*r*r;
	}
	//周长
	double circumference(){
		return 2 * pi*r;
	}
	//点和圆的关系
	//0 圆外
	//1 圆上
	//2 圆内
	int relation(Point b){
		double dst = b.distance(p);
		if (sgn(dst - r) < 0)return 2;
		else if (sgn(dst - r) == 0)return 1;
		return 0;
	}
	//线段和圆的关系
	//比较的是圆心到线段的距离和半径的关系
	int relationseg(Line v){
		double dst = v.dispointtoseg(p);
		if (sgn(dst - r) < 0)return 2;
		else if (sgn(dst - r) == 0)return 1;
		return 0;
	}
	//直线和圆的关系
	//比较的是圆心到直线的距离和半径的关系
	int relationline(Line v){
		double dst = v.dispointtoline(p);
		if (sgn(dst - r) < 0)return 2;
		else if (sgn(dst - r) == 0)return 1;
		return 0;
	}
	//两圆的关系
	//5 相离
	//4 外切
	//3 相交
	//2 内切
	//1 内含
	//需要 Point 的 distance
	//测试:UVA12304
	int relationcircle(circle v){
		double d = p.distance(v.p);
		if (sgn(d - r - v.r) > 0)return 5;
		if (sgn(d - r - v.r) == 0)return 4;
		double l = fabs(r - v.r);
		if (sgn(d - r - v.r) < 0 && sgn(d - l) > 0)return 3;
		if (sgn(d - l) == 0)return 2;
		if (sgn(d - l) < 0)return 1;
		return 0;
	}
	//求两个圆的交点,返回 0 表示没有交点,返回 1 是一个交点,2 是两个交点
	//需要 relationcircle
	//测试:UVA12304
	int pointcrosscircle(circle v, Point &p1, Point &p2){
		int rel = relationcircle(v);
		if (rel == 1 || rel == 5)return 0;
		double d = p.distance(v.p);
		double l = (d*d + r*r - v.r*v.r) / (2 * d);
		double h = sqrt(r*r - l*l);
		Point tmp = p + (v.p - p).trunc(l);
		p1 = tmp + ((v.p - p).rotleft().trunc(h));
		p2 = tmp + ((v.p - p).rotright().trunc(h));
		if (rel == 2 || rel == 4)
			return 1;
		return 2;
	}
	//求直线和圆的交点,返回交点个数
	int pointcrossline(Line v, Point &p1, Point &p2){
		if (!(*this).relationline(v))return 0;
		Point a = v.lineprog(p);
		double d = v.dispointtoline(p);
		d = sqrt(r*r - d*d);
		if (sgn(d) == 0){
			p1 = a;
			p2 = a;
			return 1;
		}
		p1 = a + (v.e - v.s).trunc(d);
		p2 = a - (v.e - v.s).trunc(d);
		return 2;
	}
	//得到过 a,b 两点,半径为 r1 的两个圆
	int gercircle(Point a, Point b, double r1, circle &c1, circle &c2){
		circle x(a, r1), y(b, r1);
		int t = x.pointcrosscircle(y, c1.p, c2.p);
		if (!t)return 0;
		c1.r = c2.r = r;
		return t;
	}
	//得到与直线 u 相切,过点 q, 半径为 r1 的圆
	//测试:UVA12304
	int getcircle(Line u, Point q, double r1, circle &c1, circle &c2){
		double dis = u.dispointtoline(q);
		if (sgn(dis - r1 * 2) > 0)return 0;
		if (sgn(dis) == 0){
			c1.p = q + ((u.e - u.s).rotleft().trunc(r1));
			c2.p = q + ((u.e - u.s).rotright().trunc(r1));
			c1.r = c2.r = r1;
			return 2;
		}
		Line u1 = Line((u.s + (u.e - u.s).rotleft().trunc(r1)), (u.e +
			(u.e - u.s).rotleft().trunc(r1)));
		Line u2 = Line((u.s + (u.e - u.s).rotright().trunc(r1)), (u.e
			+ (u.e - u.s).rotright().trunc(r1)));
		circle cc = circle(q, r1);
		Point p1, p2;
		if (!cc.pointcrossline(u1, p1, p2))cc.pointcrossline(u2, p1, p2)
			;
		c1 = circle(p1, r1);
		if (p1 == p2){
			c2 = c1;
			return 1;
		}
		c2 = circle(p2, r1);
		return 2;
	}
	//同时与直线 u,v 相切,半径为 r1 的圆
	//测试:UVA12304
	int getcircle(Line u, Line v, double r1, circle &c1, circle &c2,
		circle &c3, circle &c4){
		if (u.parallel(v))return 0;//两直线平行
		Line u1 = Line(u.s + (u.e - u.s).rotleft().trunc(r1), u.e + (u
			.e - u.s).rotleft().trunc(r1));
		Line u2 = Line(u.s + (u.e - u.s).rotright().trunc(r1), u.e + (
			u.e - u.s).rotright().trunc(r1));
		Line v1 = Line(v.s + (v.e - v.s).rotleft().trunc(r1), v.e + (v
			.e - v.s).rotleft().trunc(r1));
		Line v2 = Line(v.s + (v.e - v.s).rotright().trunc(r1), v.e + (
			v.e - v.s).rotright().trunc(r1));
		c1.r = c2.r = c3.r = c4.r = r1;
		c1.p = u1.crosspoint(v1);
		c2.p = u1.crosspoint(v2);
		c3.p = u2.crosspoint(v1);
		c4.p = u2.crosspoint(v2);
		return 4;
	}
	//同时与不相交圆 cx,cy 相切,半径为 r1 的圆
	//测试:UVA12304
	int getcircle(circle cx, circle cy, double r1, circle &c1, circle &
		c2){
		circle x(cx.p, r1 + cx.r), y(cy.p, r1 + cy.r);
		int t = x.pointcrosscircle(y, c1.p, c2.p);
		if (!t)return 0;
		c1.r = c2.r = r1;
		return t;
	}
	//过一点作圆的切线 (先判断点和圆的关系)
	//测试:UVA12304
	int tangentline(Point q, Line &u, Line &v){
		int x = relation(q);
		if (x == 2)return 0;
		if (x == 1){
			u = Line(q, q + (q - p).rotleft());
			v = u;
			return 1;
		}
		double d = p.distance(q);
		double l = r*r / d;
		double h = sqrt(r*r - l*l);
		u = Line(q, p + ((q - p).trunc(l) + (q - p).rotleft().trunc(h)))
			;
		v = Line(q, p + ((q - p).trunc(l) + (q - p).rotright().trunc(h))
			);
		return 2;
	}
	//求两圆相交的面积
	double areacircle(circle v){
		int rel = relationcircle(v);
		if (rel >= 4)return 0.0;
		if (rel <= 2)return min(area(), v.area());
		double d = p.distance(v.p);
		double hf = (r + v.r + d) / 2.0;
		double ss = 2 * sqrt(hf*(hf - r)*(hf - v.r)*(hf - d));
		double a1 = acos((r*r + d*d - v.r*v.r) / (2.0*r*d));
		a1 = a1*r*r;
		double a2 = acos((v.r*v.r + d*d - r*r) / (2.0*v.r*d));
		a2 = a2*v.r*v.r;
		return a1 + a2 - ss;
	}
	//求圆和三角形 pab 的相交面积
	//测试:POJ3675 HDU3982 HDU2892
	double areatriangle(Point a, Point b){
		if (sgn((p - a) ^ (p - b)) == 0)return 0.0;
		Point q[5];
		int len = 0;
		q[len++] = a;
		Line l(a, b);
		Point p1, p2;
		if (pointcrossline(l, q[1], q[2]) == 2){
			if (sgn((a - q[1])*(b - q[1])) < 0)q[len++] = q[1];
			if (sgn((a - q[2])*(b - q[2])) < 0)q[len++] = q[2];
		}
		q[len++] = b;
		if (len == 4 && sgn((q[0] - q[1])*(q[2] - q[1])) > 0)swap(q[1], q
			[2]);
		double res = 0;
		for (int i = 0; i < len - 1; i++){
			if (relation(q[i]) == 0 || relation(q[i + 1]) == 0){
				double arg = p.rad(q[i], q[i + 1]);
				res += r*r*arg / 2.0;
			}
			else{
				res += fabs((q[i] - p) ^ (q[i + 1] - p)) / 2.0;
			}
		}
		return res;
	}
};
int main()
{
#ifdef LOCAL
	freopen("C:/input.txt", "r", stdin);
#endif
	int cx, cy, r, x1, y1, y2;
	cin >> cx >> cy >> r >> x1 >> y1 >> y2;
	Point A(cx, cy), B(x1, y1), C(0, y2);
	circle cir(A, r);
	Line L(B, C);
	Point D, E;
	cir.pointcrossline(L, D, E);
	//cout << B.distance(D) << endl;
	//cout << B.distance(E) << endl;
	ll ans = B.distance(D) * B.distance(E) + 1e-6;
	cout << ans << endl;

	return 0;
}

B Chino with Repeater

#include 
#include 
#define fst first
#define sed second
using namespace std;
typedef long long ll;

const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;

int main()
{
#ifdef LOCAL
	//freopen("C:/input.txt", "r", stdin);
#endif
	ll n, x = 1, k = 0;
	cin >> n;
	while (x < n)
		x <<= 1, ++k;
	cout << k << endl;

	return 0;
}

C Chino with Queue <状压dp>

令f[i][j]队伍末尾为i已经安排状态为j的代价,首先将每个人单独在第一个的代价计算出。
枚举每个状态,如果当前没有i有j则尝试将i安排在j的后面,并加上对应的舒适度取max。

#include 
#include 
#define fst first
#define sed second
using namespace std;
typedef long long ll;

const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
const int N = 19;
int g[N][N];
int f[N][1 << N]; //队伍末尾为i已经安排状态为j的代价

int main()
{
#ifdef LOCAL
	freopen("C:/input.txt", "r", stdin);
#endif
	int n;
	cin >> n;
	for (int i = 0; i < n; ++i) //编号0~n-1
		for (int j = 0; j < n; ++j)
			scanf("%d", &g[i][j]);
	for (int i = 0; i < n; ++i)
		f[i][1 << i] = g[i][i]; //i在队首
	for (int s = 1; s < (1 << n); ++s) //前推后
	{
		for (int i = 0; i < n; ++i)
			if ((s & (1 << i)) == 0) //没有这个人
				for (int j = 0; j < n; ++j) //枚举当前状态
					if (s & (1 << j))
						f[i][s | (1 << i)] = max(f[i][s | (1 << i)], f[j][s] + g[i][j]); //在当前的j后面加上i
	}
	int ans = 0;
	for (int i = 0; i < n; ++i)
		ans = max(ans, f[i][(1 << n) - 1]);
	cout << ans << endl;

	return 0;
}

D Chino with Equation <组合数>

#include 
#include 
#define fst first
#define sed second
using namespace std;
typedef long long ll;

const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
const int MOD = 1e9 + 7;
const int N = 2e6 + 100;

ll fac[N], inv[N];
ll qpow(ll a, ll n, ll m)
{
	ll t = 1;
	while (n)
	{
		if (n & 1)
			t = (t * a) % m;
		a = (a * a) % m, n >>= 1;
	}
	return t;
}
ll C(int n, int m)
{
	//return fac[n] * inv[m] % MOD * inv[n - m] % MOD;
	return fac[n] * qpow(fac[m], MOD - 2, MOD) % MOD * qpow(fac[n - m], MOD - 2, MOD) % MOD;
}
int main()
{
#ifdef LOCAL
	//freopen("C:/input.txt", "r", stdin);
#endif
	fac[0] = inv[0] = 1;
	for (int i = 1; i < N; i++)
	{
		fac[i] = fac[i - 1] * i % MOD;
		//inv[i] = qpow(fac[i], MOD - 2, MOD);
	}
	int n, m;
	cin >> m >> n;
	assert(n <= 1e6 + 10 && m <= 1e6 + 10);
	printf("%lld %lld\n", C(n - 1, m - 1), C(n - 1 + m, m - 1));

	return 0;
}

F Chino with Expectation <前缀和>

#include 
#include 
#define fst first
#define sed second
using namespace std;
typedef long long ll;

const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
const int N = 1e5 + 10;
ll s[N];

int main()
{
#ifdef LOCAL
	freopen("C:/input.txt", "r", stdin);
#endif
	int n, q;
	cin >> n >> q;
	for (int i = 1; i <= n; ++i)
		scanf("%lld", &s[i]), s[i] += s[i - 1];
	for (int j = 0; j < q; ++j)
	{
		int x, l, r;
		scanf("%d%d%d", &x, &l, &r);
		double res = 1.0 * (s[r] - s[l - 1]) / (r - l + 1) + 1.0 * x / n;
		printf("%f\n", res);
	}

	return 0;
}

G Chino with Train to the Rabbit Town <贪心>

贪心策略,如果能组成一段异或和为k的就直接让他成为一组,后面的继续进行匹配。
使用变量x记录异或前缀和,不断地将出现的值插入map中,并将x异或上k,如果能在map中找到则说明从之前某个位置开始到当前位置异或和为k。

#include 
#include 
#define fst first
#define sed second
using namespace std;
typedef long long ll;

const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;

int main()
{
#ifdef LOCAL
	freopen("C:/input.txt", "r", stdin);
#endif
	int n, k;
	cin >> n >> k;
	int x = 0, y, ans = 0;
	set<int> st;
	for (int i = 1; i <= n; ++i)
	{
		st.insert(x);
		scanf("%d", &y);
		x ^= y;
		y = x ^ k;
		auto it = st.find(y);
		if (it != st.end() && *it == y)
		{
			ans++;
			x = 0;
			st.clear();
		}
	}
	cout << ans << endl;

	return 0;
}

H Chino with Ciste <搜索>

题目要求转向次数最小并且到达终点,输出转向次数。直接使用普通BFS无法求解,因为路径最短不一定转向次数最少。
在移动时增加一些策略,当前以i方向移动则一直移动下去直到撞墙或出界,并在路径中将未访问的节点入队并增加一次转向。
每个入队节点表示尝试从当前节点进行转向。则最先到达每个位置的路径必定是转向最少的。

#include 
#include 
#define fst first
#define sed second
using namespace std;
typedef long long ll;

const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
const int N = 2e3 + 10;
int dir[4][2] = { 0, 1, 0, -1, 1, 0, -1, 0 };
char g[N][N];
bool vis[N][N];
int n, m, sx, sy;

struct node
{
	int x, y, k;
};
int BFS()
{
	queue<node> q;
	q.push({ sx, sy, 0 });
	vis[sx][sy] = 1;
	while (!q.empty())
	{
		int x = q.front().x, y = q.front().y, k = q.front().k; q.pop();
		for (int i = 0; i < 4; ++i)
		{
			int xx = x + dir[i][0], yy = y + dir[i][1];
			while (xx >= 1 && xx <= n && yy >= 1 && yy <= m && g[xx][yy] != '*') //不撞墙不停
			{
				if (!vis[xx][yy]) //没访问过再入点
				{
					if (g[xx][yy] == 'T')
						return k;
					vis[xx][yy] = 1;
					q.push({ xx, yy, k + 1 }); //尝试在当前点转向
				}
				xx += dir[i][0], yy += dir[i][1]; //不转向继续走次数不增加
			}
		}
	}
	return -1;
}
int main()
{
#ifdef LOCAL
	freopen("C:/input.txt", "r", stdin);
#endif
	cin >> n >> m;
	for (int i = 1; i <= n; ++i)
	{
		scanf("%s", g[i] + 1);
		for (int j = 1; j <= m; ++j)
			if (g[i][j] == 'S')
				sx = i, sy = j;
	}
	int res = BFS();
	if (~res)
		printf("%d\n", res);
	else
		printf("troil\n");

	return 0;
}

你可能感兴趣的:(_动态规划_,搜索,_计算几何_,贪心,前缀和,状压dp,组合数)