AtCoder Beginner Contest 189
E - Rotate and Flip
题解:
- ( x , y ) (x, y) (x,y)顺时针旋转90°后变成 ( y , − x ) (y, -x) (y,−x)
- ( x , y ) (x, y) (x,y)逆时针旋转90°后变成 ( − y , x ) (-y, x) (−y,x)
- ( x , y ) (x, y) (x,y)以 x = p x = p x=p对称时变成 ( 2 p − x , y ) (2p - x, y) (2p−x,y)
- ( x , y ) (x, y) (x,y)以 y = p y = p y=p对称时变成 ( x , 2 p − y ) (x, 2p - y) (x,2p−y)
有了这个我们只需要在 记录每次旋转的变换参数, 后面直接代入x, y的坐标就能求出答案了。
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 7;
typedef long long ll;
ll n, x[N], y[N], m, q;
ll a[N], b[N], fza[N], fzb[N], visa[N], visb[N];
int main() {
ios::sync_with_stdio(0);
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> x[i] >> y[i];
}
cin >> m;
a[0] = 0, b[0] = 0;
fza[0] = fzb[0] = 1;
visa[0] = 1, visb[0] = 2;
for (int i = 1; i <= m; i++) {
int op;
cin >> op;
if (op == 3) {
ll p;
cin >> p;
a[i] = 2 * p - a[i - 1];
b[i] = b[i - 1];
visa[i] = visa[i - 1];
visb[i] = visb[i - 1];
fza[i] = -fza[i - 1];
fzb[i] = fzb[i - 1];
} else if (op == 4) {
ll p;
cin >> p;
b[i] = 2 * p - b[i - 1];
fzb[i] = -fzb[i - 1];
a[i] = a[i - 1];
visa[i] = visa[i - 1];
visb[i] = visb[i - 1];
fza[i] = fza[i - 1];
} else if (op == 2) {
if (visa[i - 1] == 1) {
visa[i] = 2;
visb[i] = 1;
} else {
visa[i] = 1;
visb[i] = 2;
}
a[i] = b[i - 1];
b[i] = a[i - 1];
fza[i] = fzb[i - 1];
fzb[i] = fza[i - 1];
fza[i] = -fza[i];
a[i] = -a[i];
} else {
if (visa[i - 1] == 1) {
visa[i] = 2;
visb[i] = 1;
} else {
visa[i] = 1;
visb[i] = 2;
}
a[i] = b[i - 1];
b[i] = a[i - 1];
fza[i] = fzb[i - 1];
fzb[i] = fza[i - 1];
fzb[i] = -fzb[i];
b[i] = -b[i];
}
}
int q; cin >> q;
while (q--) {
int A, B;
cin >> A >> B;
ll ansx = x[B], ansy = y[B];
if (visa[A] == 1) {
ansx = ansx * fza[A] + a[A];
ansy = ansy * fzb[A] + b[A];
} else {
ll cnt = ansx;
ansx = ansy * fza[A] + a[A];
ansy = cnt * fzb[A] + b[A];
}
cout << ansx << " " << ansy << endl;
}
}
F - Sugoroku2
题解:
设 d p [ i ] dp[i] dp[i]为从第 i i i个位置走到大于等于 n n n的期望步数。
那么:
d p [ i ] = d p [ i + 1 ] + d p [ i + 2 ] + d p [ i + 3 ] … … + d p [ i + m ] m + 1 m ∗ m dp[i] = \frac{dp[i + 1] + dp[i + 2] + dp[i + 3] ……+dp[i + m]}{m} + \frac{1}{m} * m dp[i]=mdp[i+1]+dp[i+2]+dp[i+3]……+dp[i+m]+m1∗m
如果第 i i i个位置可以回到原点, 那么:
d p [ i ] = d p [ 0 ] dp[i] = dp[0] dp[i]=dp[0]
有了这个好像无法算出答案, 因为陷入了死循环。
但是, 如果把 d p [ 0 ] dp[0] dp[0]看成一个参数
用公式表示的话:
递推到最后一次的结果一定是:
d p [ 0 ] = a ∗ d p [ 0 ] + b dp[0] = a * dp[0] + b dp[0]=a∗dp[0]+b
一元一次方程, 直接解出来就行了。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 7;
int a[N], n, m, k, vis[N];
long double dp[N][2];
int main() {
cin >> n >> m >> k;
for (int i = 1; i <= k; i++) {
cin >> a[i];
vis[a[i]] = 1;
}
double sum = 0, cnt = 0;
int count = 0;
for (int i = n - 1; i >= 0; i--) {
if (vis[i]) {
dp[i][0] = 1.0;
} else {
dp[i][1] = ( sum) / (long double) m + 1;
dp[i][0] = cnt / (long double) m;
}
sum = sum + dp[i][1];
cnt = cnt + dp[i][0];
sum -= dp[i + m][1];
cnt -= dp[i + m][0];
}
if (fabs(dp[0][0] - 1.00) <= 0.000000001) {
puts("-1");
} else {
printf("%.4Lf\n", dp[0][1] / (1 - dp[0][0]));
}
}