2017 ACM/ICPC Asia Regional Qingdao Online【solved:7 / 11】
hdu 6206 Apple(計算幾何+java高精度)
題意:給你三個點,保證不再同一條直線上,再給你一點,問你是否在這三個點形成的圓外。
思路:用java套個板子即可。就是求出三個點外接圓的圓心和半徑判斷下。
import java.math.BigInteger;
import java.math.BigDecimal;
import java.util.Scanner;
public class Main {
public static void main(String args[]) {
Scanner in = new Scanner(System.in );
int t = in.nextInt();
while (t > 0) {
t--;
long x1,y1,x2,y2,x3,y3,x,y;
x1 = in.nextLong();
y1 = in.nextLong();
x2 = in.nextLong();
y2 = in.nextLong();
x3 = in.nextLong();
y3 = in.nextLong ();
x = in.nextLong();
y = in.nextLong();
BigDecimal X1 = new BigDecimal(x1);
BigDecimal Y1 = new BigDecimal(y1);
BigDecimal X2 = new BigDecimal(x2);
BigDecimal Y2 = new BigDecimal(y2);
BigDecimal X3 = new BigDecimal(x3);
BigDecimal Y3 = new BigDecimal(y3);
BigDecimal X = new BigDecimal(x);
BigDecimal Y = new BigDecimal(y);
BigDecimal a1 = X2.subtract(X1);
BigDecimal b1 = Y2.subtract(Y1);
BigDecimal two = new BigDecimal(2);
BigDecimal c1 = (a1.multiply(a1).add(b1.multiply(b1))).divide(two);
BigDecimal a2 = X3.subtract(X1);
BigDecimal b2 = Y3.subtract(Y1);
BigDecimal c2 = (a2.multiply(a2).add(b2.multiply(b2))).divide(two);
BigDecimal d = a1.multiply(b2).subtract(a2.multiply(b1));
BigDecimal cpx = X1.add((c1.multiply(b2).subtract(c2.multiply(b1))).divide(d));
BigDecimal cpy = Y1.add((a1.multiply(c2).subtract(a2.multiply(c1))).divide(d));
//System.out.println(cpx.doubleValue());
//System.out.println(cpy.doubleValue());
BigDecimal r = X1.subtract(cpx).multiply(X1.subtract(cpx)).add(Y1.subtract(cpy).multiply(Y1.subtract(cpy)));
BigDecimal dist = X.subtract(cpx).multiply(X.subtract(cpx)).add(Y.subtract(cpy).multiply(Y.subtract(cpy)));
if (dist.compareTo(r) == 1) {
System.out.println("Accepted");
}else {
System.out.println("Rejected");
}
}
}
}
hdu 6208 The Intersection(AC自動機)
題意:給你n個字串,問你其中是否存在某個串,滿足所有的串的都是它的子串。
思路:AC自動機水題。注意卡IO。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
struct AC
{
int nxt[maxn][30],FAIL[maxn],edd[maxn],root,L;//nxt記錄節點,在這裡edd指標代表以當前節點為字串尾的字串個數
int mark[maxn];
int newnode()
{
for(int i=0; i<26; i++)
nxt[L][i]=-1;//節點連線的邊初始化為-1
edd[L]=0;
mark[L]=0;
return L++;
}
void init()
{
L=0;
root=newnode();
}
void insert(char buf[])//trie樹的建立
{
int now=root;
int l = strlen(buf);
for(int i=0; i<l; i++)
{
if(nxt[now][buf[i]-'a']==-1)nxt[now][buf[i]-'a']=newnode();
now=nxt[now][buf[i]-'a'];
}
edd[now]++;
}
void build()//建立ac自動機
{
queue<int>que;
for(int i=0; i<26; i++)
{
if(nxt[root][i]==-1)nxt[root][i]=root;
else //若有連邊則將節點加入佇列 ,並將FAIL指標指向root
{
FAIL[nxt[root][i]]=root;
que.push(nxt[root][i]);
}
}
while(!que.empty())
{
int now=que.front();
que.pop();
for(int i=0; i<26; i++)
{
if(nxt[now][i]==-1) //若無連邊,則將該邊指向當前節點FAIL指標指向的相應字元連線的節點
nxt[now][i]=nxt[FAIL[now]][i];
else //若有連邊,則將兒子節點的FAIL指標指向當前節點FAIL指標指向相應字元接的節點
{
FAIL[nxt[now][i]]=nxt[FAIL[now]][i];
que.push(nxt[now][i]); //加入佇列繼續遍歷
}
}
}
}
int query(char buf[])
{
int now=root;
int res=0;
int l = strlen(buf);
for(int i=0; i<l; i++)
{
now=nxt[now][buf[i]-'a'];
int temp=now;
while(temp!=root&&mark[temp]==0)//根據題目要求改變形式
{
res+=edd[temp];
edd[temp]=0;
mark[temp]=1;
temp=FAIL[temp];
}
}
return res; //在這裡返回的是匹配到的模式串的數量
}
}ac;
char s[maxn], longest[maxn];
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
int n;
scanf("%d", &n);
ac.init();
getchar();
int maxLen = 0;
for(int i = 0; i < n; i++)
{
gets(s);
int len = strlen(s);
if(len > maxLen)
{
maxLen = len;
strcpy(longest, s);
}
ac.insert(s);
}
ac.build();
int sum = ac.query(longest);
if(sum == n) puts(longest);
else puts("No");
}
return 0;
}
hdu 6209 The Intersection(整數化小數)
題意:等價於讓你用分子分母均不大於100000的分數形式,去精確表示一個小數。
思路:stern brocot tree。知道這個就很簡單了,在樹上二分找即可。這題卡long double。
#include <bits/stdc++.h>
using namespace std;
int ansl, ansr;
void solve(int l1, int r1, int l2, int r2, long double decimal)
{
if (l1 == l2 && r1 == r2) return;
if (fabs((long double)1.0 * l1 / r1 - decimal) < fabs((long double)1.0 * ansl / ansr - decimal)) ansl = l1, ansr = r1;
if (fabs((long double)1.0 * l2 / r2 - decimal) < fabs((long double)1.0 * ansl / ansr - decimal)) ansl = l2, ansr = r2;
int ml = (l1 + l2);
int mr = (r1 + r2);
if (mr > 100000) return;
if ((long double)1.0 * ml / mr >= decimal) solve(l1, r1, ml, mr, decimal);
else solve(ml, mr, l2, r2, decimal);
}
void gao(int k)
{
for(int i = 1; i <= 50; i++)
{
if(i * i * i == k)
{
printf("%d/1\n", i * i);
return ;
}
}
long double temp = pow((long double)k, (long double)2.0 / 3);
int lb = floorl(temp);//floor函式:向下舍入
long double rb = temp - lb;
ansl = 0, ansr = 1;
solve(0, 1, 1, 1, rb);
printf("%d/%d\n", lb * ansr + ansl, ansr);
}
int main()
{
int T, k;
scanf("%d", &T);
while(T--)
{
scanf("%d", &k);
gao(k);
}
return 0;
}
hdu 6213 Chinese Zodiac(water)
#include <bits/stdc++.h>
using namespace std;
string s[] = {"rat", "ox", "tiger", "rabbit", "dragon", "snake", "horse", "sheep", "monkey", "rooster", "dog" ,"pig"};
int main()
{
int T;
scanf("%d", &T);
map<string, int>ma;
for(int i= 0; i <12; i++)
ma[s[i]] = i;
while(T--)
{
string a, b;
cin >> a >>b;
int x = ma[a], y = ma[b];
int ans = y - x;
if(ans <= 0) ans += 12;
printf("%d\n", ans);
}
return 0;
}
hdu 1009 Smallest Minimum Cut (最小割的最小邊集)
題意:給一個圖,求一個最小割的最小邊集的大小。
思路:邊權擴大一個相對較大的係數倍,然後最大流/係數就是最大流,最大流%係數就是最小割的最小邊集。
#include <bits/stdc++.h>
using namespace std;
const int maxv = 200 + 5;
struct Dinic
{
int vs, es;
struct edge{int to, cap, rev;};
vector<edge>G[maxv];
int level[maxv];//頂點到源點的距離標號
int iter[maxv];//當前弧,在其之前的邊已經沒有用了
// void init()
// {
//}
void addedge(int from, int to, int cap)
{
G[from].push_back({to, cap, (int)G[to].size()});
G[to].push_back({from, 0, (int)G[from].size() - 1});
}
void bfs(int s)
{
memset(level, -1, sizeof(level));
queue<int>que;
level[s] = 0;
que.push(s);
while(que.size())
{
int v = que.front();que.pop();
for(auto &e : G[v])
{
if(e.cap > 0 && level[e.to] == -1)
{
level[e.to] = level[v] + 1;
que.push(e.to);
}
}
}
}
//dfs找增廣路
int dfs(int v, int t, int f)
{
if(v == t) return f;
for(int &i = iter[v]; i < G[v].size(); i++)
{
edge &e = G[v][i];
if(e.cap > 0 && level[v] < level[e.to])
{
int d = dfs(e.to, t, min(f, e.cap));
if(d > 0)
{
e.cap -= d;
G[e.to][e.rev].cap += d;
return d;
}
}
}
return 0;
}
int max_flow(int s, int t)
{
int flow = 0;
for(;;)
{
bfs(s);
if(level[t] == -1) return flow;
memset(iter, 0, sizeof(iter));
int f;
while((f = dfs(s, t, 0x3f3f3f3f)) > 0)
{
flow += f;
}
}
}
};
int main()
{
int T, vs, es, s, t;
scanf("%d", &T);
while(T--)
{
scanf("%d%d%d%d", &vs, &es, &s, &t);
Dinic dinic;
dinic.vs = vs, dinic.es = es;
for(int i = 0, u, v, w; i < es; i++)
{
scanf("%d%d%d", &u, &v, &w);
dinic.addedge(u, v, w * (vs + 1)+ 1);
}
printf("%d\n", dinic.max_flow(s, t) % (vs + 1));
}
return 0;
}
hdu 6215 Brute Force Sorting(思維?)
題意:給一個長度為n的序列,重複以下操作,刪除不合法的數字,直到全部符合為止。注意:比如第一輪時,如果a[4]被刪除了,a[5]仍然要和a[4]和a[6]比較。同一輪內的刪除操作是同時刪除的。
A number A[i] of the array is sorted if it satisfies the following requirements.
1. A[i] is the first element of the array, or it is no smaller than the left one A[i−1].
2. A[i] is the last element of the array, or it is no bigger than the right one A[i+1].
思路:找出每一個單調非減的區間,然後考慮每一個數字只會被最多兩個區間選擇作為刪除物件,所以是
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
const int INF = 0x3f3f3f3f;
int main()
{
int T, n;
scanf("%d", &T);
while(T--)
{
scanf("%d", &n);
vector<int>a, ans;
a.resize(n + 5);
for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
a[n + 1] = 0x3f3f3f3f;
vector<pair<int, int>>vec;
int last = -1, lb;
for(int i = 1; i <= n; i++)
{
if(last == -1) last = lb = i;
else if(a[last] <= a[i] && a[i] <= a[i + 1]) last = i;
else
{
vec.push_back({lb, last});
vec.push_back({i, i});
last = -1;
}
}
if(last != -1) vec.push_back({lb, last});
int update = 1;
while(update && vec.size())
{
update = 0;
vector<pair<int, int>>temp;
int INF = 0x3f3f3f3f;
vector<pair<int, int>>veccc;
veccc = vec;
for(int i = 0; i < vec.size() - 1; i++)
{
int lb1 = vec[i].first;
int rb1 = vec[i].second;
int lb2 = vec[i + 1].first;
int rb2 = vec[i + 1].second;
if(a[rb1] > a[lb2]) rb1--, lb2++, update = 1;
veccc[i].second = min(veccc[i].second, rb1);
veccc[i+1].first = max(veccc[i + 1].first, lb2);
}
vec.clear();
for(auto o : veccc)
{
if(o.first > o.second) continue;
vec.push_back(o);
}
a = ans;
}
for(auto o: vec)
{
for(int i = o.first; i <= o.second; i++)
{
ans.push_back(a[i]);
}
}
printf("%d\n", ans.size());
for(int i= 0; i < ans.size(); i++)
printf("%d ", ans[i]);
puts("");
}
return 0;
}
hdu 6216 A Cubic number and A Cubic Number(water)
題意:給出一個質數p(
p≤1e12 ),問你它是否為兩個完全立方數的差。
思路:即p為質數時,
#include <bits/stdc++.h>
using namespace std;
long long Zcsqrt(long long p)
{
long long temp = sqrt(p);
temp = max(0LL, temp - 5);
while((temp + 1) * (temp + 1) <= p) temp++;
return temp;
}
bool solve(long long p)
{
long long delta = 12LL * p - 3;
if(delta <= 0) return false;
long long sqrtDelta = Zcsqrt(delta);
if(sqrtDelta * sqrtDelta != delta) return false;
sqrtDelta -= 3;
if(sqrtDelta % 6 != 0) return false;
return true;
}
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
long long p;
scanf("%lld", &p);
if(solve(p)) puts("YES");
else puts("NO");
}
return 0;
}