AtCoder Beginner Contest 168 (A~E,E題很有意思)
比賽連結:Here
AB水題,
C - : (Colon)
時針轉過得角度為:\(2π \times \frac{h + \frac m{12}}{12}\)
分針轉過得角度為:\(2π \times \frac{m}{60}\)
const double pi = acos(-1.0); int main() { double a, b, h, m; cin >> a >> b >> h >> m; long double rad = pi * 2 * ((long double)h / 12.0 + ((long double)m / 60.0) / 12.0 - (long double)m / 60.0); long double rsq = (long double)(a * a + b * b) - (long double)(2 * a * b) * cosl(rad); printf("%20.20Lf\n", sqrtl(rsq)); return 0; }
D - .. (Double Dots)
\(N\)個點 \(M\) 條邊的圖,讓你在每個點指明一個方向(就是下一個點),使得從每個點出發,沿著點的指定方向走最終能到達點 \(1\)
如果可以,輸出 yes
,並且給出每個點指明的方向,否則輸出 no
直接反著考慮,從點 \(1\) 出發的 \(BFS\)
const int N = 1e5 + 10; vector<ll>e[N]; int main() { cin.tie(nullptr)->sync_with_stdio(false); int n, m; cin >> n >> m; for (int i = 0, u, v; i < m; ++i) { cin >> u >> v, u--, v--; e[u].push_back(v); e[v].push_back(u); } vector<ll>dis(n, -1); queue<ll>q; q.push(0), dis[0] = 0; while (!q.empty()) { int u = q.front(); q.pop(); for (int v : e[u]) { if (dis[v] == -1) dis[v] = u, q.push(v); } } cout << "Yes\n"; for (int i = 1; i < n; ++i) cout << dis[i] + 1 << "\n"; }
E - ∙ (Bullet)
小兔捕獲了 \(N\) 條不同的沙丁魚,第 \(i\) 條沙丁魚的 美味程度 和 香味程度 分別是 \(A_i\) 和 \(B_i\)
她想在這些沙丁魚中選擇 一條 或者 多條 放入冷凍箱;但是必須保證沙丁魚的選擇是合格的
合格的定義:其中的任意兩條沙丁魚 \(i\) 和 \(j\) 都不滿足 \(A_i×A_j+B_i×B_j=0\)
小兔想知道有多少種選擇沙丁魚的方法(選擇的沙丁魚的集合相同,算同一種方法),答案對 \(1e9+7\) 取模
簡化題意:
\(N\) 個點,每個點給出 \(A_i,B_i\)
在一個集合中,不難存在滿足 \(A_iB_j + A_jB_i = 0\)
的點對現在問能選出多少這樣的集合,注意對 \(1e9 + 7\) 取模
資料範圍
- \(1\le N\le 2e5\)
- \(-10^{18}\le A_i,B_i\le 10^{18}\)
\[QAQ \]
需要不滿足的式子與 \(i\) 和 \(j\) 的關係太大了,不妨化簡一下:
\(A_i×A_j+B_i×B_j=0 \to A_i\times A_j = -B_i\times B_j \to \frac{A_i}{B_i}=-\frac{B_j}{A_j}\)
所以可能有很多點 \(\frac{A_i}{B_i}\) 相等,把他們染成相同的顏色
然後不能和他們同時出現的顏色就是 \(-\frac{B_j}{A_j}\) ,找出他們即可
但是注意,這裡等式轉換的前提是 \(A_i \not =0,B_i\not =0\)
所以有四種情況:
- \(A_i = 0,B_i =0\)
- \(A_i \not =0,B_i =0\)
- \(A_i=0,B_i\not =0\)
- \(A_i \not =0,B_i\not =0\)
其中,
①和其他三種都不能在一個集合
②和③不能在一個集合
④中某些點不能在一個集合
那麼我們直接染色找即可
還有一個問題
就是 \(\frac{A_i}{B_i}\) 是一個小數,如果我們用 map 來存有可能精度不夠,所以將 \(\frac{A_i}{B_i}\) 轉化為分數 \(a\frac bc\) 的三元組 \((a, b, c)\) 來記錄,還要考慮一下符號,所以用兩個 map
最後我們都找到了後,要考慮計算答案
對於一種顏色來說,假如它有 \(Siz\) 各點
每個點選和不選兩種情況,總的就是 \(2^{Siz}\) 種情況,再減去全都不選的情況,所以最終這個顏色的選法就是 \(2^{Siz} - 1\)
然後假如不能和他同時選的另一種顏色是 \(rhs[color]\)
那麼就是三種情況
- 選 \(color\)
- 選 \(rhs[color]\)
- 都不選
這樣考慮即可
typedef pair<int, int> pii;
typedef pair<int, pii> piii;
const int MAX = 2e5 + 10;
const ll mod = 1000000007;
int N;
ll siz[MAX], rhs[MAX], col, vis[MAX];
ll f[MAX], num1, num2;
map<piii, int> mp[2];
inline piii calc(ll x, ll y) {
x = abs(x), y = abs(y);
ll gcd = __gcd(x % y, y);
return piii{x / y, {x % y / gcd, y / gcd}};
}
int main() {
scanf("%d", &N);
f[0] = 1;
for (int i = 1; i <= N; i++) f[i] = 1ll * f[i - 1] * 2 % mod;
for (int i = 0; i <= N; i++) f[i] = (f[i] - 1 + mod) % mod;
ll ans = 0;
for (int i = 1; i <= N; i++) {
ll a, b; scanf("%lld%lld", &a, &b);
if (a == 0 && b == 0) ans++;//a=0,b=0,只能選和不選
else if (a == 0) num1++;
else if (b == 0) num2++;
else {
piii now = calc(a, b), pre = calc(b, a);//轉化為三元組
int state = 0;//判斷符號
if (1.0 * a / b > 0) state = 1;
if (!mp[state].count(now)) {
mp[state][now] = ++col;
if (mp[state ^ 1].count(pre))
rhs[col] = mp[state ^ 1][pre], rhs[mp[state ^ 1][pre]] = col;
}
siz[mp[state][now]]++;
}
}
ll t = (f[num1] + f[num2] + 1) % mod;//a = 0, b != 0 和 a!=0, b = 0
for (int i = 1; i <= col; i++)
if (!vis[i]) {
vis[i] = 1;
if (rhs[i]) {
vis[rhs[i]] = 1;
t = t * ((1ll + (f[siz[i]] + f[siz[rhs[i]]]) % mod) % mod) % mod;
}
else t = t * ((1ll + f[siz[i]]) % mod) % mod;
}
ans = (ans + t) % mod;
printf("%lld\n", (ans - 1 + mod) % mod);
}
寫法改進
const int mod = 1e9 + 7;
ll qpow(ll a, ll b) {
ll ans = 1;
for (; b; b >>= 1, a = a * a % mod) if (b & 1) ans = ans * a % mod;
return ans;
}
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
ll n; cin >> n;
map<pair<ll, ll>, pair<ll, ll>> m;
ll ans = 1, P = mod - 1;
for (int i = 0; i < n; ++i) {
ll a, b;
cin >> a >> b;
if (!a && !b) P += 1;
else {
ll g = __gcd(a, b);
a /= g, b /= g;
if (b < 0) a = -a, b = -b;
if (a <= 0) m[ {b, -a}].second++;
else m[ {a, b}].first ++;
}
}
for (auto u : m) ans = ans * (qpow(2, u.second.first) + qpow(2, u.second.second) - 1 + mod) % mod;
cout << (ans + P) % mod;
}
The desire of his soul is the prophecy of his fate
你靈魂的慾望,是你命運的先知。