2020年04月11日 组队赛
C - Game of Taking Stones
题意:题目的大概意思是两个人,两堆石头,有如下取石头的方法:
- 从其中一堆中取任意不为0颗石头;
- 从两堆中取相等同数量的石头。
假使谁先将两堆石头取完,谁就获胜。若先手获胜,则输出:1;若后手获胜,则输出:2。题目存在解。
题解:这是一道典型的博弈裸题——威佐夫博弈 +高精度。
关于具体什么是威佐夫博弈具体可以参照如下博客理解:
这里还要注意一个问题:高精度
import java.util.*; import java.math.*; public class Main { public static void main(String args[]) { Scanner cin=new Scanner(System.in); BigDecimal l=BigDecimal.valueOf(2); BigDecimal r=BigDecimal.valueOf(3); BigDecimal tmp=BigDecimal.valueOf(1); for(int i=1;i<=500;i++) { BigDecimal mid=l.add(r).divide(BigDecimal.valueOf(2)); tmp=mid; if(mid.multiply(mid).compareTo(BigDecimal.valueOf(5))<0) { l=mid; } else { r=mid; } } tmp=tmp.add(BigDecimal.valueOf(1)); tmp=tmp.divide(BigDecimal.valueOf(2)); BigDecimal a,b; while(cin.hasNext()) { a=cin.nextBigDecimal(); b=cin.nextBigDecimal(); if(a.compareTo(b)>0) { BigDecimal t=a; a=b; b=t; } BigDecimal k=b.subtract(a); k=k.multiply(tmp); k=k.setScale(0,BigDecimal.ROUND_DOWN); if(k.compareTo(a)==0) { System.out.println(0); } else { System.out.println(1); } } } }
D - A Simple Math Problem
题意:这一题的题意比较容易懂,给出如下两个条件:
- X+Y=a
- Least Common Multiple (X, Y) =b
求符合两个条件的X,Y。
题解:这是一道典型的数论题,这里还有一个重要的数学结论,
根据如下公式:
- X+Y=a
- lcm(X,Y)=b
- gcd(X,Y)*lcm(X,Y)=X*Y
由(1),(2)可推出结论:
4. gcd(X,Y)=gcd(a,b)
则结合以上相关公式可推出如下方程,解如下方程即可:
X*(X-a)=b*gcd(a,b)
代码:
#include<iostream> #include<algorithm> #include<cstring> #include<cmath> #include <iostream> #include <algorithm> #include <cmath> #define ll long long using namespace std; int main() { ll a,b; while(cin>>a>>b) { ll c=__gcd(a,b); ll t=a*a-4*b*c; if(t<0) cout<<"No Solution"<<endl; else { ll e=(ll)sqrt(t*1.0); if(e*e!=t) { cout<<"No Solution"<<endl; } else { ll x1=(a+e)/2; ll x2=(a-e)/2; ll x=min(x1,x2); cout<<x<<" "<<a-x<<endl; } } } return 0; }
H - To begin or not to begin
题意:这一题的题意比较简单,两个人轮流抽球,谁抽到红球谁就获胜。
题解:这一题也是个简单的博弈,类似买彩票一样,买的数量越多,获胜率越高。当然唯一不同的是,在这到题目中不需要“本钱”。
代码:
#include<iostream> using namespace std; int main(){ int n; while(cin>>n){ int t=n+1; if(t%2==0){ cout<<0<<endl;; }else{ cout<<1<<endl;; } } return 0; }
I - Convex
题意:求凸边形的面积。
题解:签到题,注意弧度与角度的转换方法。
代码:
#include<iostream> #include<cstring> #include<algorithm> #include<stdio.h> #include<math.h> #define ll long long using namespace std; const double pi=3.14159265358979323; int main(){ int n,d; int temp; while(cin>>n>>d){ double ans=0; for(int i=0;i<n;i++){ cin>>temp; ans=ans+d*d*sin(pi*temp/180)*0.5; } printf("%.3f\n",ans); } return 0; }
J - Find Small A
题意:字符 'a' 的ASCII码为97.现在,找出给定数组中出现了多少次 'a' 。注意,此处的数字为计算机中的32位整数。这表示,1个数字由四个字符组成(一个字符由8位二 进制数组成)。输出一个整数,表示‘a’出现的次数
题解:这一题就有意思了,比赛的时候根本看不懂,对亏了队友,我的理解是:对于数组中出现的每一个元素,将其化为2进制形式,然后每8位为一组,判断这8位数据的10进制表示是否为97,是则进行计数。
代码:
#include <iostream> #include<cstring> #include<algorithm> using namespace std; int main() { int N, n, cnt = 0; int x = 255; cin >> N; for (int i = 0; i < N; ++i) { cin >> n; do { if ((n & x) == 'a') { cnt += 1; } n >>= 8; } while (n); } cout << cnt << endl; return 0; }