2018-2019 ACM-ICPC 焦作 现场赛 A(签到)D(几何)E(规律)F(加强版bfs)I(思维)

本文解析了Codeforces2018焦作赛题A至F及I题,涵盖旅行者问题、几何漂移、并联电阻、蜂巢路径及点间距离最大化等,详细介绍了各题的题意、解题思路及代码实现。

A. Xu Xiake in Henan Province(签到)

题目链接:codeforces2018 焦作 A

题意: 

    输入4个数,代表去过 4 个地方,如果 4 个数都是 0,输出 Typically Otaku,如果有 3 个 0,输出 Eye-opener,如果有 2 个 0,输出 Young Traveller,如果有 1 个 0,输出 Excellent Traveller,如果没有 0,输出 Contemporary Xu Xiake

解题思路:

   ....无

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 1e5+5;
const double pi = acos(-1);
int a[maxn];
int main(){
	int t;
	cin >> t;
	while(t--){
		int a, ans = 0;
		for(int i = 1; i <= 4; i++){
			cin >> a;
			if(a != 0){
				ans++;
			}
		}
		if(ans == 0){
			cout << "Typically Otaku" << endl;
		}
		if(ans == 1){
			cout << "Eye-opener" << endl;
		}
		if(ans == 2){
			cout << "Young Traveller" << endl;
		}
		if(ans == 3){
			cout << "Excellent Traveller" << endl;
		}
		if(ans == 4){
			cout << "Contemporary Xu Xiake" << endl;
		}
	}
	return 0;
}

D. Keiichi Tsuchiya the Drift King(几何)

题目链接:codeforces 2018焦作 D

题意:

    弯道漂移,在车(车子抽象为矩形)不碰到两边马路的情况下,马路的最小宽度。

解题思路:

   其实只有两种状态

1.  弯道很短,所以车子在前车身出了弯道的情况下,后车身还没进弯道,如图所示

已知a,b,r,角SOT,现在求 W

在三角形 UOK 中 ∠UOK = atan( UK / UO)         [ UK = b,   UO = a+r ]

那么∠TOK = ∠UOK- ∠SOT

OK = b / sin(∠UOK)

OT = r + W = OK * cos(∠TOK)

将变量带入得

W = b / sin(∠UOK) * cos(∠TOK)   - r  =  b / sin(atan(b / (a + r))) * cos(atan(b / (a + r)) - d)

2.弯道足够长,以至于在漂移过程中车身全部可以在圆弧内,如下图所示

W = OT - r

∠UOT = atan(TU / UO)

OT = TU / sin(∠UOT)

W = b / sin(∠UOT)  - r  = b / sin(atan(TU / UO))  - r ;

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const double pi = acos(-1);
int main(){
	int t;
	cin >> t;
	while(t--){
		double a, b, r, d;
		cin >> a >> b >> r >> d;
		double o = atan(b/(a+r));
		double ans = b / sin(o);
		if(o > d/180.0 * pi){
			o = o - d / 180.0 * pi;
			ans = ans * cos(o) - r;
		}
		else{
			ans = ans - r;
		}
		printf("%.15lf\n", ans);
	}
	return 0;
}

E. Resistors in Parallel(规律)【我这种菜鸡找不出来】

题目链接:codeforces 2018焦作 E

题意:

选一个小于等于n(10^100)的无平方因子的数,它的电阻阻值就是它的所有因子的倒数和的倒数,求这个最小的阻值。

解题思路:

   打表找规律,

分子后一个等于前一个乘以2,3,5,7,11..

分母1 3 12 72 576.... 等于前一个乘2+1, 3+1,5+1 ,7+1

n太大,所以用java大数写

import java.util.*;
import java.math.*;
public class Main {
	static Scanner cin = new Scanner (System.in);
	static boolean [] vis = new boolean [521];
	static BigInteger [] dp = new BigInteger[521];
	static int [] pr = new int [521];
	static int cnt=0;
	static void getpr() {//欧拉筛    找素数
		vis[0]=vis[1]=true;
		for (int i = 2; i <= 520;i++) {//只要使所有的素数乘起来大于10^100就好
			if(!vis[i]) pr[++cnt]=i;
			for (int j = 1; j <= cnt && i*pr[j] <= 520;j++) {
				vis[i*pr[j]]=true;
				if(i%pr[j]==0) break;
			}
		}
	}
	public static void main(String[] args) {
		getpr();
		int t=cin.nextInt();
		while(t-->0) {
			int k;
			BigInteger sum = cin.nextBigInteger();
			BigInteger ans = BigInteger.ONE;
			dp[0]=BigInteger.ONE;
			for (k = 1;ans.multiply(BigInteger.valueOf(pr[k])).compareTo(sum)<=0;k++) {
				ans=ans.multiply(BigInteger.valueOf(pr[k]));
			}
			k--;
			for (int i = 1; i <= k;i++) {
				dp[i]=dp[i-1].add(dp[i-1].multiply(BigInteger.valueOf(pr[i])));
			}
			BigInteger gcd=ans.gcd(dp[k]);
			System.out.println(ans.divide(gcd)+"/"+dp[k].divide(gcd));//直接除以最大公因数
		}
	}
}

F. Honeycomb(加强BFS)

题目链接:codeforces 2018焦作 F

题意:

   给定n ,m表示一共 n 行,每行m个蜂巢,求从S到T的最短路径

解题思路:

  思路来自大佬  :   大佬博客

   从蜂巢正中心出发,然后向6个方向走,判断是否有墙,将每个蜂巢的中心点当做固定点,即要到达这个蜂巢就将坐标定位在这个蜂巢的中心点

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
const int N = 1e4+5;
char G[N][N];
int n, m, sx, sy;
int mov[6][2]={ {-2,0},{2,0},{-1,-3},{-1,3},{1,-3},{1,3}  };
struct node{
	int x, y, step;
}; 
int bfs() {
   queue<node> q;
   q.push((node){sx, sy, 1});
   while(!q.empty()) {
      node e = q.front();
		q.pop();
      for(int i = 0; i < 6; i++) {
         int x1 = e.x + mov[i][0];
         int y1 = e.y + mov[i][1];
         int x2 = x1 + mov[i][0];
         int y2 = y1 + mov[i][1]; 
         if(G[x1][y1] == ' ' && G[x2][y2] == 'T'){
         	return e.step+1;
			}
         if(G[x1][y1] != ' ' || G[x2][y2] != ' '){
				continue;
			}
         G[x2][y2] = '$';
         q.push((node){x2, y2, e.step+1});
      }
   }
   return INF;
}
int main(){
   int t;
	scanf("%d", &t);
   while(t--){
      scanf("%d%d", &n, &m);
      getchar();
      n = n * 4 + 3;
		m = m * 6 + 3;
      for(int i = 1; i <= n; i++) {
         char ch;
			G[i][0] = ' ';
			int j = 1;
         while(~scanf("%c", &ch) && ch != '\n') {
            G[i][j] = ch;
            if(ch == 'S'){
           		sx = i;
					sy = j;	
				}
            j++;
         }
			G[i][j] = '\0';
        }
      int ans = bfs(); 
      if(ans == INF) printf("-1\n");
      else printf("%d\n",ans);
   }
   return 0;
}

I. Distance(思维)

题目链接:codeforces 2018焦作 I

题意:

   给你n个点相邻点之间的距离

  让你选(1~n)个点,使它们之间的距离和最大

   输出选(1~n)个点的情况

解题思路:

    分析得出,分别从两边往中间选是最优的,那样中间的距离可以被利用多次(注意开long long ) 否则wrong anser 2

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5+5;
ll a[maxn];
int main(){
	int t;
	cin >> t;
	while(t--){
		ll n, sum = 0;
		cin >> n;
		for(int i = 1; i < n; i++){
			cin >> a[i];
			sum = sum + a[i];
		}
		ll m = sum, ans = sum, l = 1;
		cout << 0 << " " << sum;
		for(int i = 1; i < n -1; i++){
			if(i % 2 == 0){
				sum =  sum - a[l] - a[n-l];
				m = m + sum;
				l++;
			}
			ans = ans + m;
			cout << " " << ans;
		}
		cout << endl;
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值