问题 A: Tobaku Mokushiroku Kaiji
时间限制: 1 Sec 内存限制: 128 MB
题目描述
Kaiji正在与另外一人玩石头剪刀布。双方各有一些代表石头、剪刀、布的卡牌,每局两人各出一张卡牌,根据卡牌的内容决定这一局的胜负。胜负规则为:石头赢剪刀、剪刀赢布、布赢石头、相同为平局。每张卡牌至多被使用一次。
已知双方的卡牌数量,问Kaiji最多赢几局?
已知双方的卡牌数量,问Kaiji最多赢几局?
输入
一行六个数字0≤a,b,c,d,e,f≤50,a,b,c分别表示Kaiji的石头、剪刀、布的牌的数量,d,e,f分别表示此时另一人的石头、剪刀、布的牌的数量。
输出
一个整数表示Kaiji最多赢几局。
样例输入
29 7 41 14 12 42
样例输出
33
水题
#include <bits/stdc++.h>
#define maxn 100005
using namespace std;
typedef long long ll;
int main()
{
int a,b,c,d,e,f;
cin>>a>>b>>c>>d>>e>>f;
int ans=min(a,e)+min(b,f)+min(c,d);
printf("%d\n",ans);
}
问题 B: Utawarerumono
题目描述
算术是为数不多的会让久远感到棘手的事情。通常她会找哈克帮忙,但是哈克已经被她派去买东西了。于是她向你寻求帮助。
给出一个关于变量x,y的不定方程ax+by=c,显然这个方程可能有多个整数解。久远想知道如果有解,使得p2*x2+p1*x+q2*y2+q1*y最小的一组整数解是什么。为了方便,你只需要输出p2*x2+p1*x+q2*y2+q1*y的最小值。
给出一个关于变量x,y的不定方程ax+by=c,显然这个方程可能有多个整数解。久远想知道如果有解,使得p2*x2+p1*x+q2*y2+q1*y最小的一组整数解是什么。为了方便,你只需要输出p2*x2+p1*x+q2*y2+q1*y的最小值。
输入
第一行三个空格隔开的整数a,b,c(0≤a,b,c≤105)。
第二行两个空格隔开的整数p1,p2(1≤p1,p2≤105)。
第三行两个空格隔开的整数q1,q2(1≤q1,q2≤105)。
第二行两个空格隔开的整数p1,p2(1≤p1,p2≤105)。
第三行两个空格隔开的整数q1,q2(1≤q1,q2≤105)。
输出
如果方程无整数解,输出"Kuon"。
如果有整数解,输出p2*x2+p1*x+q2*y2+q1*y的最小值。
如果有整数解,输出p2*x2+p1*x+q2*y2+q1*y的最小值。
样例输入
2 2 1
1 1
1 1
样例输出
Kuon
使用扩展欧几里得计算出x,y的通解。容易发现,当x,y较大时,x^x与y^y占主导。枚举x,y,但需要卡住一个范围,让所求值不爆longlong.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll ex_gcd(ll a,ll b,ll &x,ll &y)
{
if(b==0)
{
x=1;
y=0;
return a;
}
ll ans=ex_gcd(b,a%b,x,y);
ll temp=x;
x=y;
y=temp-(a/b)*x;
return ans;
}
int main()
{
ll a,b,c;
//freopen("in.txt","w",stdout);
ll p1,p2,q1,q2;
cin>>a>>b>>c>>p1>>p2>>q1>>q2;
ll x,y;
if(a==0&&b==0&&c==0)
{
printf("0\n");
return 0;
}
if(a==0&&b==0&&c!=0)
{
printf("Kuon\n");
return 0;
}
if(a==0||b==0)
{
if(a==0)
{
if(c%b==0)
{
ll y=c/b;
ll ans=q2*y*y+q1*y;
ll temp= -p1/(2*p2);
//ll tmpp=temp*temp*p2+p1*temp;
//ans+=tmpp;
printf("%lld\n",ans);
}
else if(c%b!=0)
{
printf("Kuon\n");
}
}
else
{
if(c%a==0)
{
ll x=c/a;
ll ans=p1*x*x+p1*x;
ll temp= -q1/(2*q2);
//ll tmpp=temp*temp*q2+q1*temp;
//ans+=tmpp;
printf("%lld\n",ans);
}
else if(c%a!=0)
{
printf("Kuon\n");
}
}
return 0;
}
ll g=ex_gcd(a,b,x,y);
if(c%g!=0)
{
printf("Kuon\n");
}
else
{
ll d=c/g;
x*=d,y*=d;
x=(x%b+b)%b;
y=(c-a*x)/b;
a/=g,b/=g,c/=g;
ll ans=p2*x*x+p1*x+q2*y*y+q1*y;
ll xx=x,yy=y;
ll f1=sqrt((ll)4e18/p2);
ll f2=sqrt((ll)4e18/p1);
for(ll i=1;i<=1e6;i++)
{
x+=b;
y-=a;
//printf("%lld %lld\n",x,y);
if(abs(x)>1e6+10) break;
if(abs(y)>1e6+10) break;
ll temp=p2*x*x+p1*x+q2*y*y+q1*y;
ans=min(temp,ans);
}
for(int i=1;i<=1e6;i++)
{
xx-=b;
yy+=a;
//printf("%lld %lld\n",xx,yy);
if(abs(xx)>1e6+10) break;
if(abs(yy)>1e6+10) break;
ll temp=p2*xx*xx+p1*xx+q2*yy*yy+q1*yy;
ans=min(temp,ans);
}
printf("%lld\n",ans);
}
return 0;
}
问题 D: Eustia of the Tarnished Wings
题目描述
Novus Aither是一个潜藏着多个势力的城市。每个势力都有一个唯一的领导人,每个领导人有一个属性值。如果两个势力的领导人的属性值分别为a,b,且∣a−b∣≤m,说明这两个领导人的思想有一定的相似之处,这两个势力可以合并,新的领导人可以指定为原来的两个领导人中的任意一个。
问在所有可能的情况中,最少会剩下几个势力。
问在所有可能的情况中,最少会剩下几个势力。
输入
第一行两个空格隔开的整数n(1≤n≤106),m(0≤m≤109)。n代表当前势力的个数。m的含义如题目描述。
第二行n个空格隔开的整数di(0≤di≤109),代表第i个势力的领导人的属性值。
第二行n个空格隔开的整数di(0≤di≤109),代表第i个势力的领导人的属性值。
输出
输出一个数表示势力的最少数量。
样例输入
4 1
2 1 3 10
样例输出
2
对能力排序,从小到大往上合并,如果能合并,cnt++。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 5;
int a[maxn];
int main()
{
// freopen("in.txt", "r", stdin);
int n, m;
scanf("%d%d", &n, &m);
for (int i = 0; i < n; ++i)
scanf("%d", &a[i]);
sort(a, a + n);
int cnt = n;
for (int i = 1; i <= n; ++i)
if (abs(a[i] - a[i - 1]) <= m)
--cnt;
printf("%d\n", cnt);
return 0;
}
问题 H: Princess Principal
题目描述
阿尔比恩王国(the Albion Kingdom)潜伏着一群代号“白鸽队(Team White Pigeon)”的间谍。在没有任务的时候,她们会进行各种各样的训练,比如快速判断一个文档有没有语法错误,这有助于她们鉴别写文档的人受教育程度。
这次用于训练的是一个含有n个括号的文档。括号一共有mm种,每种括号都有左括号和右括号两种形式。我们定义用如下的方式定义一个合法的文档:
1.一个空的字符串是一个合法的文档。
2.如果A,B都是合法的文档,那么AB也是合法的文档。
3.如果S是合法的文档,那么aSb也是合法的文档,其中a,b是同一种括号,并且a是左括号,b是右括号。
现在给出q个询问,每次询问只考虑文档第ll至rr个字符的情况下,文档是不是合法的。
这次用于训练的是一个含有n个括号的文档。括号一共有mm种,每种括号都有左括号和右括号两种形式。我们定义用如下的方式定义一个合法的文档:
1.一个空的字符串是一个合法的文档。
2.如果A,B都是合法的文档,那么AB也是合法的文档。
3.如果S是合法的文档,那么aSb也是合法的文档,其中a,b是同一种括号,并且a是左括号,b是右括号。
现在给出q个询问,每次询问只考虑文档第ll至rr个字符的情况下,文档是不是合法的。
这题感觉蛮难的啊,不知道为什么训练赛的时候那么多人A。
反正我到现在都只能勉强理解这个神仙做法。
首先我们考虑一个括号序列,它合法的条件是其区间内的所有括号序列。那么其实中间的这些括号是可以抵消的。
然后就可以O(n)预处理,每次处理的时候看栈是否为空,如果空的话,肯定是可行的。然后如果可以匹配,就弹出栈顶,并标记数组编号为之后栈顶的编号。
最后判断f[l-1]是否等于f[r]。
emmm可能说的不是很清楚,因为我自己也没怎么理解为什么能这样搞。
#include <bits/stdc++.h>
#define maxn 1000005
using namespace std;
stack<int> s;
int a[maxn];
int f[maxn];
int main()
{
int n,m,q;
scanf("%d%d%d",&n,&m,&q);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
for(int i=1;i<=n;i++)
{
if(s.empty())
{
s.push(i);
f[i]=i;
}
else
{
if(a[s.top()]+1==a[i]&&a[i]%2==1)
{
s.pop();
if(s.empty()) f[i]=0;
else f[i]=s.top();
}
else
{
s.push(i);
f[i]=i;
}
}
}
for(int i=1;i<=q;i++)
{
int l,r;
scanf("%d%d",&l,&r);
if(f[l-1]==f[r]) printf("Yes\n");
else printf("No\n");
}
return 0;
}
输入
第一行两个整数n,m,q(1≤n,m,q≤106)。
第二行有n个空格隔开的整数x,第i个整数xi(0≤xi<m∗2)代表文档中的第i个字符是第⌊x/2⌋种括号,且如果xi是偶数,它代表一个左括号,否则它代表一个右括号。
接下来q行,每行两个空格隔开的整数l,r(1≤l≤r≤n),代表询问第l至r个字符构成的字符串是否是一个合法的文档。
第二行有n个空格隔开的整数x,第i个整数xi(0≤xi<m∗2)代表文档中的第i个字符是第⌊x/2⌋种括号,且如果xi是偶数,它代表一个左括号,否则它代表一个右括号。
接下来q行,每行两个空格隔开的整数l,r(1≤l≤r≤n),代表询问第l至r个字符构成的字符串是否是一个合法的文档。
输出
输出共q行,如果询问的字符串是一个合法的文档,输出"Yes",否则输出"No"。
样例输入
6 4 3
0 2 3 1 4 7
1 4
1 5
5 6
样例输出
Yes
No
No
队友写的,待补。
问题 J: New Game
时间限制: 1 Sec 内存限制: 128 MB Special Judge
题目描述
Eagle Jump公司正在开发一款新的游戏。泷本一二三作为其员工,获得了提前试玩的机会。现在她正在试图通过一个迷宫。
这个迷宫有一些特点。为了方便描述,我们对这个迷宫建立平面直角坐标系。迷宫中有两条平行直线 L1:Ax+By+C1=0,L2:Ax+By+C2=0,还有 n 个圆
。角色在直线上、圆上、圆内行走不消耗体力。在其他位置上由S点走到T点消耗的体力为S和T的欧几里得距离。
泷本一二三想从L1出发,走到L2。请计算最少需要多少体力。
这个迷宫有一些特点。为了方便描述,我们对这个迷宫建立平面直角坐标系。迷宫中有两条平行直线 L1:Ax+By+C1=0,L2:Ax+By+C2=0,还有 n 个圆

泷本一二三想从L1出发,走到L2。请计算最少需要多少体力。
输入
第一行五个正整数n,A,B,C1,C2(1≤n≤1000,−10000≤A,B,C1,C2≤10000),其中A,B 不同时为 0。
接下来 n 行每行三个整数x,y,r(−10000≤x,y≤10000,1≤r≤10000) 表示一个圆心为 (x,y),半径为 r 的圆。
接下来 n 行每行三个整数x,y,r(−10000≤x,y≤10000,1≤r≤10000) 表示一个圆心为 (x,y),半径为 r 的圆。
输出
仅一行一个实数表示答案。与标准答案的绝对误差或者相对误差不超过10-4即算正确。
样例输入
2 0 1 0 -4
0 1 1
1 3 1
样例输出
0.236068
把线看成点,到每个圆的距离为线到圆心的距离减去半径,两个圆之间距离为圆心间距离减两半径。
距离不能为负的,所以要对0取max
最后跑最短路即可。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e3 + 105;
struct circle
{
double x,y,r;
}a[maxn];
struct Edge
{
int v,next;
double w;
}edge[maxn*maxn*2];
int cnt;
int head[maxn];
void addedge(int u,int v,double w)
{
edge[cnt].v=v;
edge[cnt].w=w;
edge[cnt].next=head[u];
head[u]=cnt++;
}
double dist[maxn];
void Dijstra(int s)
{
bool vis[maxn]={0};
priority_queue<pair<double,int>,vector<pair<double,int>>,greater<pair<double,int>>>q;
for(int i=1;i<maxn;i++) dist[i]=-1;
dist[s]=0;
q.push(make_pair(dist[s],s));
while(!q.empty())
{
int u=q.top().second;
q.pop();
if(vis[u])
continue;
vis[u]=true;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
double w=edge[i].w;
if((dist[v]==-1||dist[v]>dist[u]+w)&&!vis[v])
{
dist[v]=dist[u]+w;
q.push(make_pair(dist[v],v));
}
}
}
}
int main()
{
// freopen("in.txt", "r", stdin);
int n;
double x,y,c,d;
memset(head,-1, sizeof(head));
scanf("%d%lf%lf%lf%lf",&n,&x,&y,&c,&d);
for(int i=1;i<=n;i++)
{
scanf("%lf%lf%lf",&a[i].x,&a[i].y,&a[i].r);
}
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
double dd=sqrt((a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y))-a[i].r-a[j].r;
dd=max(0.0,dd);
addedge(i,j,dd);
addedge(j,i,dd);
}
}
for(int i=1;i<=n;i++)
{
double temp=fabs(x*a[i].x+y*a[i].y+c);
double v=sqrt(x*x+y*y);
double dd=temp/v-a[i].r;
dd=max(dd,0.0);
addedge(i,n+1,dd);
addedge(n+1,i,dd);
}
for(int i=1;i<=n;i++)
{
double temp=fabs(x*a[i].x+y*a[i].y+d);
double v=sqrt(x*x+y*y);
double dd=temp/v-a[i].r;
dd=max(dd,0.0);
addedge(i,n+2,dd);
addedge(n+2,i,dd);
}
double temp=fabs(c-d);
double v=sqrt(x*x+y*y);
double dd=temp/v;
addedge(n+1,n+2,dd);
addedge(n+2,n+1,dd);
Dijstra(n+1);
printf("%.6lf\n",dist[n+2]);
return 0;
}