2021牛客暑期多校训练营8
A. Ares, Toilet Ares
- 题意
厕所战神,去厕所一次就有(frac{z_i - y_i}{z_i})的可能拿到一段长度为(x_i)的代码,只有代码长度累计到l时,即可通过题目(K),并且可以通过自己的智商解决a道简单题,求能完成题目的数量
- 思路
求(a+prod_{i=1}^n(z - y) / z)即可,注意逆元和分开求即可。
code :
void solve(){
int n,m,k,a,l;
cin >> n >> m >> k >> a >> l;
ll d = a;
ll up = 1, down = 1;;
for(int i = 1;i <= k;i ++) {
ll x,y,z;
cin >> x >> y >> z;
if(x == 0) continue;
d = (d * z) % mod;
up = up * (z - y) % mod;
down = down * (pow_mod(z, mod - 2)) % mod;
}
ll ans = ((d + up) % mod + mod) * down % mod;
cout << ans << endl;
}
D. OR
- 题意
给出两个长度为(n - 1)的序列(b)和(c),需要构造一个长度为n的序列a,要求(b_i = a_{i-1} or a_i, c_i = a_{i-1} + a_i), 问最多能构造出几个序列(a).
- 思路
首先要知道定理: (a + b = a or b + a and b), 然后枚举(a_1)即可,判断是否可行即可。
思考一下,什么情况(a_{i-1})可以取一种或者两种,那么当
- ((a_i or a_{i-1} = 1) && (a_i and a_{i-1} = 1)),这样当前位(a_i)和(a_{i-1})都是1
- 同时为0的情况也一样,只能为0
- ((a_i or a_{i-1} = 1) && (a_i and a_{i-1} = 0)),那么(a_i)和(a_{i-1})就有两种选法(1,0)和(0,1).
code :
int b[N], c[N];
int a[N];
void solve(){
int n;
cin >> n;
fep(i,2,n) cin >> b[i];
fep(i,2,n) {
cin >> c[i];
c[i] -= b[i];
}
int ans = 1;
fep(k,0,30) {
int fa = 1,fb = 1;
fep(i,2,n) {
int tb = b[i] >> k & 1;
int tc = c[i] >> k & 1;
int na = 0, nb = 0;
if(tb && tc) {
nb = fb;
}else if(tb && !tc) { // 顺序变了
na = fb,nb = fa;
}else if(!tb && !tc) {
na = fa;
}
fa = na, fb = nb;
}
ans *= fa + fb;
}
cout << ans << endl;
}
E. Rise of Shadows
- 题意
问你这一年可以是闰年且是素数嘛?
- 思路
nonononono
code :
cout << "no" << endl;
F. Robots
- 题意
给一张地图,问类型为(i)的机器人是否能从(st o ed)。
- 只能向下走((x,y) o (x + 1,y))
- 只能想右走((x,y) o (x,y + 1))
- 都能走
- 思路
暴力加bitset记忆化
从后往前扫,用列记录后面所有图的可达与否即可。
code:
bitset<N * N * 2> f[N];
int a[N][N];
char str[N];
struct Query{
int x,y;
int op,id;
};
vector<Query> v[N][N];
int ans[M];
void solve(){
int n,m;
cin >> n >> m;
for(int i = 1;i <= n;i ++) {
cin >> (str + 1);
for(int j = 1;j <= m;j ++) {
a[i][j] = (str[j] - '0');
}
}
int q;
cin >> q;
for(int i = 1;i <= q;i ++) {
int op,x1,y1,x2,y2;
cin >> op >> x1 >> y1 >> x2 >> y2;
v[x1][y1].push_back({x2,y2,op,i});
}
fpp(i,n,1) {
fpp(j,m,1) {
if(!a[i][j]) {
if(!a[i][j + 1])
f[j] |= f[j + 1];
f[j][i * m + j] = 1;
}else {
f[j].reset();
}
for(auto it : v[i][j]) {
if(it.op == 2) ans[it.id] = (it.x == i);
else if(it.op == 1) ans[it.id] = (it.y == j);
else ans[it.id] = 1;
ans[it.id] &= f[j][it.x * m + it.y];
}
}
}
fep(i,1,q) {
if(ans[i]) cout << "yes" << endl;
else cout << "no" << endl;
}
}
K. Yet Another Problem About Pi
- 题意
你有一条长为(pi)的线,你可以随意构造它的形状,变成圆都可以,然后给你一个(w)和(d), 在二维平面内,每隔(w)有一条竖线,每隔(d)有一条横线,问你通过画线,最多可以和多少条线段相交(竖线和横线分开的)
- 思路
枚举斜边的情况和直边的情况即可,直边的贡献是2,斜边的贡献是3,在图上画即可。
code :
void solve(){
double w,d;
cin >> w >> d;
double hd = min(w,d);
double hy = sqrt(w * w + d * d);
int k = floor(pi / w);
int ans = 0;
for(int i = 0;i <= min(k,10);i ++) {
if(pi - i * hd > 0) ans = max(ans, (int)(2 * i + (int)((pi - i * hd) / hy) * 3));
if(pi - i * hy > 0) ans = max(ans, (int)(3 * i + (int)((pi - i * hy) / hd) * 2));
}
cout << ans + 4 << endl;
}