C - The Big Race
思路
开始读半天都没读懂,后来勇敢猜测一发结论,其实就是当跑道长度在 k∗lcm(b,w) 和 k∗lcm(b,w)+min(b,w) 之间时会出现tie的情况,然后考虑下边界情况就行了,这题的WA点相当多,压根儿没看到说当 p==0 的时候,输出 0/1 。
代码(JAVA版)
import java.util.Scanner;
import java.math.*;
import java.text.*;
public class Main
{
public static void main(String args[])
{
Scanner cin = new Scanner ( System.in );
BigInteger t,w,b,m,r,lcm,ans,last,tmp,cnt;
t = cin.nextBigInteger();
w = cin.nextBigInteger();
b = cin.nextBigInteger();
m = w.min(b);
r = w.gcd(b);
lcm = w.divide(r);
lcm = lcm.multiply(b);
cnt = t.divide(lcm);
last = cnt.multiply(lcm);
ans = cnt.multiply(m).subtract(BigInteger.ONE);
tmp = t.subtract(last).add(BigInteger.ONE);
tmp = tmp.min(m);
ans = ans.add(tmp);
if(ans.equals(BigInteger.ZERO)) {
System.out.println("0/1");//WA 点
}
else {
r = ans.gcd(t);
System.out.println(ans.divide(r)+"/"+t.divide(r));
}
}
}
D. Super M
思路
感觉其实是个简单题啊,就以特殊点构造一颗新的树,然后求一下这棵树的直径 d 就OK了。
具体:假设需要最后跑回到出发点的话,那么总的花费一定是 (2*新图边的数目 ) ,而这个值是定值, 所以不需要最后跑回到出发点的话,而且要求花费最小,那么就是 (2∗新图边的数目−d )。
代码
#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
const int MAX = 130000;
vector<int> adj[MAX];
int d[MAX], size[MAX];
bool mark[MAX];
void dfs(int p, int v)
{
size[v] = 0;
if (mark[v])
size[v] = 1;
for (int i = 0; i < adj[v].size(); i++)
{
int u = adj[v][i];
if (u != p)
{
d[u] = d[v] + 1;
dfs(v, u);
size[v] += size[u];
}
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int n, m;
cin >> n >> m;
for (int i = 0; i < n - 1; i++)
{
int u, v;
cin >> u >> v;
u--;
v--;
adj[u].push_back(v);
adj[v].push_back(u);
}
for (int i = 0; i < m; i++)
{
int v;
cin >> v;
v--;
mark[v] = true;
}
dfs(-1, 0);
int v = -1;
for (int i = 0; i < n; i++)
if (mark[i] && (v == -1 || d[v] < d[i]))
v = i;
memset(d, 0, sizeof(d));
dfs(-1, v);
int sum = 0;
int mx = 0;
for (int i = 0; i < n; i++)
{
if (size[i] > 0 && m - size[i] > 0)
sum += 2;
if (mark[i])
mx = max(mx, d[i]);
}
for (int i = 0; i < n; i++)
if (mark[i] && i < v && d[i] == mx)
{
v = i;
break;
}
cout << v + 1 << "\n" << sum - mx << "\n";
return 0;
}