CTU Open Contest 2019

A. Beer Barrels

题意:给出四个整数:A,B,K,C,A,B,C 都是大于 0 的个位数,问在所有仅由 A 或 B 组成的 K 位数中(K 位数的每一位都是 A 或 B),数字 C 的个数有多少。

题解:可以转化为二进制串1或者0出现的次数。
A!=B的情况下,所有可能共有2^k个01串,每个01串有k位,
所以一共有k* 2^k个数字,其中0和1对半,即k* 2^k/2。
需要注意分情况讨论还有模数,我就是忘了模wa了

#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <cmath>
#include <cstring>
using namespace std;
#define INF 0x3f3f3f3f

typedef long long ll;
const int p=1e9+7;
ll mod_pow(ll x, ll n, ll mod){
	ll res=1;
	while (n>0){
		if (n&1) res=res*x%mod;
		x=x*x%mod;
		n>>=1;
	}
	return res;
}

int main() {

	ios::sync_with_stdio(0);
	cin.tie(0);
	ll a,b,k,c;
	cin>>a>>b>>k>>c;
	if ((c!=a && c!=b) || k==0) cout<<"0"<<endl;
	else if (a!=b) {
		ll ans=mod_pow(2,k-1,p);
		cout<<k*ans%p<<endl;	
	}
	else
		cout<<k<<endl;
	return 0;
}
B. Beer Bill

题意:计算字符串的价格。给多个字符串,每个串占一行。字符串分两种,一种字符串名为 Raked Line 只含有 C 个’|’字符,这种字符串的价格定义为 42* C。
另一种字符串名为 PricedLine,格式 是以数字 price 开头、中间用两个字符 ,- 连接,结尾是连续 C 个 | 。,这种字符串的价格 定义为 price*C,若结尾没有‘|’出现,则 C 默认为 1 个。计算所有字符串的总价,总价向上取整到 10 的倍数。

题解:给出的串如果开头是|,则价格为:| 个数 * 42
给出的串如果开头是数字,则价格为:数字 * 后面|个数
求和即可,向上取整到10的倍数
我输出格式复制错了wa了

#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <cmath>
#include <cstring>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long ll;


int main() {

	ios::sync_with_stdio(0);
	cin.tie(0);
	string s;
	ll ans=0;
	while (cin>>s) {
		ll len=s.size();
		if (s[0]=='|') ans+=len*42;
		ll t=0;
		for (int i=0; i<len; i++) {
			if (s[i]==',') continue;
			else if (s[i]>='0' && s[i]<='9') t=t*10+(int)(s[i]-'0');
			else if (s[i]=='-') {
				ans+=(len-i-1)*t;
				break;
			}
		}
	}
	while (ans%10) {
		ans++;
	}
	cout<<ans<<",-"<<endl;
	return 0;
}
C. Beer Coasters

题意:给定一个圆的圆心和一个矩形的左下方坐标和右上方坐标,除圆的半径之外的 6 个数据均 在-1000 到 1000 范围内,圆的半径在 1 到 1000 范围。求圆与矩形相交的面积。

题解:网上找的计算几何模版
下图是烟台大学提供的题解:
在这里插入图片描述

#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <cmath>
#include <cstring>
#include <ctime>
#include <iomanip>
using namespace std;
#define INF 0x3f3f3f3f
#define eps 1e-10
#define pi acos(-1.0)
typedef long long ll;
int dcmp(double x) {
	if(fabs(x)<eps)return 0;
	return x>0?1:-1;
}
struct Point {
	double x,y;
	Point(double _x=0,double _y=0) {
		x=_x;
		y=_y;
	}
};
Point operator + (const Point &a,const Point &b) {
	return Point(a.x+b.x,a.y+b.y);
}
Point operator - (const Point &a,const Point &b) {
	return Point(a.x-b.x,a.y-b.y);
}
Point operator * (const Point &a,const double &p) {
	return Point(a.x*p,a.y*p);
}
Point operator / (const Point &a,const double &p) {
	return Point(a.x/p,a.y/p);
}
bool operator < (const Point &a,const Point &b) {
	return a.x<b.x||(dcmp(a.x-b.x)==0&&a.y<b.y);
}
bool operator == (const Point &a,const Point &b) {
	return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0;
}
double Dot(Point  a,Point b) {
	return a.x*b.x+a.y*b.y;
}
double Length(Point a) {
	return sqrt(Dot(a,a));
}
double Angle(Point a,Point b) {
	return acos(Dot(a,b)/Length(a)/Length(b));
}
double angle(Point a) {
	return atan2(a.y,a.x);
}
double Cross(Point a,Point b) {
	return a.x*b.y-a.y*b.x;
}
Point vecunit(Point a) {
	return a/Length(a);
}
Point Normal(Point a) {
	return Point(-a.y,a.x)/Length(a);
}
Point Rotate(Point a,double rad) {
	return Point(a.x*cos(rad)-a.y*sin(rad),a.x*sin(rad)+a.y*cos(rad));
}
double Area2(Point a,Point b,Point c) {
	return Length(Cross(b-a,c-a));
}
bool OnSegment(Point p,Point a1,Point a2) {
	return dcmp(Cross(a1-p,a2-p))==0&&dcmp(Dot(a1-p,a2-p))<=0;
}
struct Line {
	Point p,v;
	double ang;
	Line() {};
	Line(Point p,Point v):p(p),v(v) {
		ang=atan2(v.y,v.x);
	}
	bool operator < (const Line &L) const {
		return ang<L.ang;
	}
	Point point(double d) {
		return p+(v*d);
	}
};
bool OnLeft(const Line &L,const Point &p) {
	return Cross(L.v,p-L.p)>=0;
}
Point GetLineIntersection(Point p,Point v,Point q,Point w) {
	Point u=p-q;
	double t=Cross(w,u)/Cross(v,w);
	return p+v*t;
}
Point GetLineIntersection(Line a,Line b) {
	return GetLineIntersection(a.p,a.v,b.p,b.v);
}
double PolyArea(vector<Point> p) {
	int n=p.size();
	double ans=0;
	for(int i=1; i<n-1; i++)
		ans+=Cross(p[i]-p[0],p[i+1]-p[0]);
	return fabs(ans)/2;
}
struct Circle {
	Point c;
	double r;
	Circle() {}
	Circle(Point c, double r):c(c), r(r) {}
	Point point(double a) {
		return Point(c.x+cos(a)*r, c.y+sin(a)*r);
	}
};

bool InCircle(Point x,Circle c) {
	return dcmp(c.r-Length(c.c-x))>=0;
}
bool OnCircle(Point x,Circle c) {
	return dcmp(c.r-Length(c.c-x))==0;
}
int getSegCircleIntersection(Line L,Circle C,Point *sol) {
	Point nor=Normal(L.v);
	Line p1=Line(C.c,nor);
	Point ip=GetLineIntersection(p1,L);
	double dis=Length(ip-C.c);
	if(dcmp(dis-C.r)>0)return 0;
	Point dxy=vecunit(L.v)*sqrt(C.r*C.r-dis*dis);
	int ret=0;
	sol[ret]=ip+dxy;
	if(OnSegment(sol[ret],L.p,L.point(1)))ret++;
	sol[ret]=ip-dxy;
	if(OnSegment(sol[ret],L.p,L.point(1)))ret++;
	return ret;
}
double SegCircleArea(Circle C,Point a,Point b) {
	double a1=angle(a-C.c);
	double a2=angle(b-C.c);
	double da=fabs(a1-a2);
	if(da>pi)da=pi*2-da;
	return dcmp(Cross(b-C.c,a-C.c))*da*C.r*C.r/2.0;
}
double PolyCircleArea(Circle C,Point *p,int n) {
	double ret=0;
	Point sol[2];
	p[n]=p[0];
	for(int i=0; i<n; i++) {
		double t1,t2;
		int cnt=getSegCircleIntersection(Line(p[i],p[i+1]-p[i]),C,sol);

		if(cnt==0) {
			if(!InCircle(p[i],C)||!InCircle(p[i+1],C))ret+=SegCircleArea(C,p[i],p[i+1]);
			else ret+=Cross(p[i+1]-C.c,p[i]-C.c)/2;
		}
		if(cnt==1) {
			if(InCircle(p[i],C)&&(!InCircle(p[i+1],C)||OnCircle(p[i+1],C)))ret+=Cross(sol[0]-C.c,p[i]-C.c)/2,ret+=SegCircleArea(C,sol[0],p[i+1]);//,cout<<"jj-1"<<endl;
			else ret+=SegCircleArea(C,p[i],sol[0]),ret+=Cross(p[i+1]-C.c,sol[0]-C.c)/2;//,cout<<"jj-2"<<endl;
		}
		if(cnt==2) {
			if((p[i]<p[i+1])^(sol[0]<sol[1]))swap(sol[0],sol[1]);
			ret+=SegCircleArea(C,p[i],sol[0]);
			ret+=Cross(sol[1]-C.c,sol[0]-C.c)/2;
			ret+=SegCircleArea(C,sol[1],p[i+1]);
		}
	}
	return fabs(ret);
}

int main() {


	ios::sync_with_stdio(0);
	cin.tie(0);
	Point p[5];
	double x1,y1,x2,y2,x3,y3,R;
	cin>>x1>>y1>>R>>x2>>y2>>x3>>y3;
	Circle C=Circle(Point(x1,y1),R);
	if(x2>x3)swap(x2,x3);
	if(y2>y3)swap(y2,y3);
	p[0]=Point(x2,y2);
	p[2]=Point(x3,y3);
	p[1]=Point(x3,y2);
	p[3]=Point(x2,y3);
	double ans=PolyCircleArea(C,p,4);
	if(ans<-eps) ans=-ans;
	cout<<fixed<< setprecision(4)<<ans;
	return 0;
}
D. Beer Flood
E. Beer Game
F. Beer Marathon

题意:在一条直线上有 N 个啤酒摊,这些啤酒摊的位置在直线上随机摆放,题目要求是任何两个 连续啤酒摊位之间的距离应完全相同,并等于指定的特定值 K。问每个啤酒摊最少移动多少米 可以使他们之间的距离是 K 值(尽量减少所有啤酒摊位移动的总米数。

题解:贪心想把序列转换为a1+k,a1+2k,…,a1+nk
将排完序的a,每个a[i]-i*k得到b序列,这样每个数间的距离为k就决定了,后面问题就转化为:
∑|bi-m|最小(m为要找的基准点)
将b序列排序中间那个数就是要找的m

#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <cmath>
#include <cstring>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long ll;

const int maxn=1e6+10;
ll n,k;
ll a[maxn];
ll b[maxn]; 
int main() {

	ios::sync_with_stdio(0);
	cin.tie(0);
	cin>>n>>k;
	for (int i=1; i<=n; i++){
		cin>>a[i];
	}
	sort(a+1,a+n+1);
	for (int i=1; i<=n; i++){
		b[i]=a[i]-(ll)i*k;
	} 
	sort(b+1,b+n+1);
	ll ans=0;
	if (n&1){
		ll t=b[(n+1)/2];
		for (int i=1; i<=n; i++)
			ans+=abs(b[i]-t);
		//cout<<t<<endl;
	}
	else {
		ll t1=b[n/2];
		ll t2=b[n/2+1];
		ll ans1=0;
		ll ans2=0;
		for (int i=1; i<=n; i++)
			ans1+=abs(b[i]-t1);
		for (int i=1; i<=n; i++)
			ans2+=abs(b[i]-t2);
		ans=min(ans1,ans2);
	}
	cout<<ans<<endl;
	return 0;
}
G. Beer Mugs

题意:给你一个字符串,让你求最长的连续的一段重新改变顺序可构造成回文串的子串。

题解:异或前缀和,我们可以先将 a-t 表示成 2^0 -2^19这样的二进制的形式,然后从左到右扫一遍该字符串,求出从该字符串开头到每个位置的异或和(也就是每一个状态),并将每一个状态第一次出现的的位置进行标记。若该状态在之前已经出现过,根据异或的性质,第一次出现该状态的位置到该状态的位置的距离即为一个可构造成回文串的子串,当然有可能会出现奇数字符的子串可构造成回文串(像是abcab 这种可能不会被统计到),所以我们可以在每次循环的时候对a到t进行循环,然后对他们所表示的数进行单独异或(排除单独一个字符的影响,目的是补一个字符以避免该状态不被统计到)。

#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <cmath>
#include <cstring>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long ll;

int vis[1<<21];
int main(){
	
	ios::sync_with_stdio(0);
	cin.tie(0);
	int n;
	int sum=0;
	int ans=0;
	vis[0]=-1; //n-1-(-1)=n
	string s;
	cin>>n>>s;
	for (int i=0; i<n; i++){
		sum^=(1<<(s[i]-'a'));
		if (!vis[sum]) vis[sum]=i;
		else ans=max(ans,i-vis[sum]);
		for (int j=0; j<20; j++){
			sum^=(1<<j);
			if (vis[sum]) 
				ans=max(ans,i-vis[sum]);
			sum^=(1<<j);
		}
	}
	cout<<ans<<endl;
	return 0;
}
H. Screamers in the Storm

题意:行动规则:
狼向东走,在到最东部后会跳至最西面,然后接着向东走,周遭往复。
羊向南走,到头后和狼同理。
场地规则: 地上本是秃地,记作“ . ” 三回合后会长草,草地记作“#”,羊会吃草,吃掉三回合后草会重新长,狼会吃羊,羊死后会标记为“ * ” 如果羊 5 回合没吃草会被饿死,狼则为 10 回合,死后都会被记作“ * ”标记为“ * ”的砖块不会再长草。
输出T回合后的场地。

题解:模拟

I. Sixpack
J. Beer Vision
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值