A - Sqrt Bo(HDU 5752)
大意
定義
思路
當
代碼
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll upperBound = 4294836224LL;
ll a;
string s;
stringstream ss;
int main() {
while(cin >> s) {
if(s.size() > 10) {
puts("TAT");
continue;
}
ss.clear();
ss << s;
ss >> a;
if(a < 1 || a > upperBound) {
puts("TAT");
continue;
}
bool ok = false;
for(int i = 0; i <= 5; i++) {
if(a == 1) {
cout << i << endl;
ok = true;
break;
}
a = (ll)floor(sqrt(1.0 * a));
}
if(ok == false) {
puts("TAT");
}
}
return 0;
}
B - Permutation Bo(HDU 5753)
大意
題給一個序列
思路
根據本題的數據規模來看,肯定無法枚舉排列然後算期望了。一個可行的思維是算出序列
- 當考慮
c 的第1 個元素c1 時,我們只要考慮前兩個元素的排列,當前兩個元素呈現出c1>c2 時c1 的貢獻就會被算進期望中。顯然c1>c2 的概率是12 。 - 當考慮
c 的第2 個元素c2 時,我們只要考慮前三個元素的排列,當前三個排列呈現出c1<c2,c3<c2 時,c2 的貢獻就回被算進期望中。顯然這種排列的概率是13 。 - 第
3 到第n−1 個元素的貢獻與第2 個元素的貢獻相似。第n 個元素的貢獻與第1 個元素的貢獻相似。
於是我們枚舉每個元素,將其貢獻加入期望中即可。
代碼
#include <bits/stdc++.h>
using namespace std;
int n, a;
double ans;
int main() {
while(~scanf("%d", &n)) {
ans = 0;
for(int i = 1; i <= n; i++) {
scanf("%d", &a);
if(i == 1 || i == n) {
ans += 1.0 * a / 2;
}
else {
ans += 1.0 * a / 3;
}
}
if(n == 1) {
printf("%.5f\n", 1.0 * a);
}
else {
printf("%.5f\n", ans);
}
}
return 0;
}
C - Life Winner Bo(HDU 5754)
大意
有兩個人在國際象棋棋盤上用國際象棋一個棋子進行博弈,這個棋子可能是王,王后,城堡和騎士。棋子從座標
思路
根據國際象棋棋盤的特點,該遊戲可以抽象成從兩個石子堆(分別有
- 王:由於王可以在一次移動中橫向,縱向或斜向移動一步,因此對應到拿石子模型中,當兩堆石子的數量
N−1,M−1 都是偶數的時候當前狀態是必敗態(否則一定可以通過一次行動使得當前兩堆石子的數量變成偶數)。 - 城堡:由於城堡可以在一次移動中橫向或者縱向移動任意步,因此對應到拿石子的模型中,與
NimGame 模型是一樣的。因此只有N=M 的時候先手失敗,其餘情況下是先手獲勝(先手總可以令對方面對兩堆石子數目相同的情況,這種情況是必敗態)。 - 騎士:由於騎士可以在一次移動中橫移兩步縱移一步或橫移一步縱移兩步,因此對應到拿石子模型中,相當於在
N−1,M−1 兩堆石子中一堆拿一個,而另一堆拿兩個。當N−1+M−1 不是3 的倍數的時候一定是平局。當它是3 的倍數的時候,當N=M 時一定是必敗的,因爲只要想脫離必敗態(例如兩堆石子分別−1,−2 )就一定會被趕回必敗態(例如兩堆石子分別−2,−1 )。若N,M 不等且它們的差值爲1 時一定是必勝的,因爲必定可以用一步把對手逼入必敗態。 - 王后:由於王后可以在一次移動中橫向,縱向或斜向移動任意步,因此對應到拿石子的模型中,與
WythoffGame 模型是一樣的。因此可以用公式ai=⌊i×(1+5√)/2⌋,bi=ai+i 檢驗當前局勢(N−1,M−1) 是否是必敗局勢。
代碼
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1000;
char ch[] = {'G', 'D', 'B'};
int t, type, n, m, ans, G[maxn+5][maxn+5];
int king() {
return n % 2 == 1 && m % 2 == 1 ? -1 : 1;
}
int castle() {
return n == m ? -1 : 1;
}
int knight() {
if(n > m) {
swap(n, m);
}
if(n == m && (n - 4) % 3 == 0 && n >= 4) {
return -1;
}
if(n % 3 == 2 && m % 3 == 0 && m - n == 1) {
return 1;
}
return 0;
}
int queen() {
if(n > m) {
swap(n, m);
}
int a = n - 1, b = m - 1, k = m - n;
double tmp = (1.0 + sqrt((double)5.0)) / 2.0;
return (int)(k * tmp) == a ? -1 : 1;
}
int main() {
scanf("%d", &t);
while(t--) {
scanf("%d%d%d", &type, &n, &m);
if(type == 1) {
ans = king();
}
if(type == 2) {
ans = castle();
}
if(type == 3) {
ans = knight();
}
if(type == 4) {
ans = queen();
}
printf("%c\n", ch[ans+1]);
}
return 0;
}
J - Rower Bo(HDU 5761)
大意
主人公要駕船從平面直角座標系中的
思路
再思考無果的時候,不妨將問題轉化一下:主人公從
設T爲主人公要花的時間,另外主人公在
對豎直方向有
此時還有一個條件沒有利用,那就是主人公的速度方向始終朝向終點,那麼對主人公當前位置到目的地的方向有
最後聯立這三個方程可得
於是原問題得解。
代碼
#include <bits/stdc++.h>
using namespace std;
int a, v1, v2;
int main() {
while(~scanf("%d%d%d", &a, &v1, &v2)) {
if(a == 0) {
puts("0.00000");
}
else if(v1 <= v2) {
puts("Infinity");
}
else {
printf("%.5f\n", 1.0 * v1 * a / (v1 * v1 - v2 * v2));
}
}
return 0;
}
K - Teacher Bo(HDU 5762)
大意
題給
思路
雖然看上去不同的二元組會很多,但是根據鴿巢原理,當
代碼
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
bool ok;
int t, n, m, dx, dy, mht, x[maxn], y[maxn], vis[maxn];
int main() {
scanf("%d", &t);
while(t--) {
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++) {
scanf("%d%d", &x[i], &y[i]);
}
memset(vis, 0, sizeof(vis));
ok = false;
for(int i = 1; i <= n; i++) {
for(int j = i + 1; j <= n; j++) {
dx = abs(x[i] - x[j]);
dy = abs(y[i] - y[j]);
mht = dx + dy;
if(vis[mht] == true) {
ok = true;
i = n + 1;
break;
}
vis[mht] = true;
}
}
puts(ok ? "YES" : "NO");
}
return 0;
}
(其它題目略)