因【牛客版权】不放题面了
A.小沙的炉石
思路
假设我们攻击了 a a a次,那么 a a a次攻击的伤害范围我们是可以求出来的,伤害最低的打一次回一次蓝的模式,伤害最高是先把所有加蓝卡用完,再攻击a次,然后没提前一个位置使用蓝卡,伤害就会+1(可以抽象为二进制,蓝卡的位置对总伤害的贡献与二进制的1的位置,对答案的贡献类似)
通过假设我们可以得到一个离散区间 [ a 2 , a m + a ( a + 1 ) 2 ] [a^2,am+\frac{a(a+1)}{2}] [a2,am+2a(a+1)],这个是攻击 a a a的所有可能伤害。
所以我们对每一个 x x x,判断其与这个区间的关系就可以。
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int main() {
ll n, m, k; cin >> n >> m >> k;
while (k--) {
ll a, x; cin >> x;
a = sqrt(x);
a = min(a, min(n, m + 1));
if (a * m + a * (1 + a) / 2 < x) cout << "NO" << "\n";
else cout << "YES" << "\n";
}
}
F.小沙的算数
思路
因为乘法的优先级是高于加法的,且同级的只有一个运算符,这大大简化了题目难度
我们只需要把乘法的分为一组,加法的分为一组,因为改变乘法组内数字 ,并不影响加法组,同理,改变加法组也一样。
因为取模除法,需要逆元。
反思:当时没过因为偷懒,看数据范围累乘的结果爆不了ll,不取模,直接除,这样就不用写快速幂了,然后wa了,没找到错误就遁了
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll maxn = 1e6 + 10;
const ll mod = 1e9 + 7;
ll n, q, a[maxn], book[maxn], sum[maxn];
char s[maxn];
ll qpow(ll a, ll x) {
ll res = 1;
while (x) {
if (x & 1) res = res * a % mod;
a = a * a % mod;
x >>= 1;
}
return res;
}
int main() {
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
cin >> n >> q;
int t = 1;
for (int i = 1; i < n; i++) cin >> s[i];
for (int i = 1; i <= n; i++) cin >> a[i];
sum[1] = a[1];
book[1] = 1;
for (int i = 2; i <= n; i++) {
if (s[i - 1] == '*') {
book[i] = t;
sum[t] = sum[t] * a[i] % mod;
}
else {
sum[++t] = a[i];
book[i] = t;
}
}
long long ans = 0;
for (int i = 1; i <= t; i++) ans = (ans + sum[i]) % mod;
while (q--) {
int x, y;
cin >> x >> y;
ans = (ans - sum[book[x]] + mod) % mod;
sum[book[x]] = sum[book[x]] * qpow(a[x], mod - 2) % mod * y % mod;
ans = (ans + sum[book[x]]) % mod;
a[x] = y;
cout << ans << endl;
}
return 0;
}
G.小沙的身法
思路
简化目的:给定 ( x , y ) (x,y) (x,y),求 x − > y x->y x−>y的最短路径的体力消耗,造成体力消耗的原因为从低处往高处走($a[u]<a[v] $)
我们可以建立两个数组(思路为前缀和),load[i]
表示从
p
o
i
n
t
[
1
]
point[1]
point[1]走到
p
o
i
n
t
[
i
]
point[i]
point[i]的体力消耗,reload[i]
表示从
p
o
i
n
t
[
i
]
point[i]
point[i]走到
p
o
i
n
t
[
1
]
point[1]
point[1]的体力消耗。
因为题目给的地图为无向图,所以最短路径为x->p->y
,
p
=
l
c
a
(
x
,
y
)
p=lca(x,y)
p=lca(x,y)
所以得到答案方程:
a
n
s
=
a
[
x
]
+
r
e
l
o
a
d
[
x
]
−
r
e
l
o
a
d
[
p
]
+
l
o
a
d
[
y
]
−
l
o
a
d
[
p
]
ans=a[x]+reload[x]-reload[p]+load[y]-load[p]
ans=a[x]+reload[x]−reload[p]+load[y]−load[p]
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 1e6 + 10;
ll a[maxn], load[maxn], reload[maxn];
int head[maxn], nex[2 * maxn], w[2 * maxn], dis[maxn], fa[maxn], num[maxn], node[maxn], cnt;
void add(int u, int v) {
num[u]++;
w[++cnt] = v;
nex[cnt] = head[u];
head[u] = cnt;
}
void dfs(int index, int reindex, int top) {
node[index] = top;
fa[index] = reindex;
load[index] = load[reindex];
reload[index] = reload[reindex];
if (a[index] > a[reindex]) load[index] += a[index] - a[reindex];
else if (a[index] < a[reindex]) reload[index] += a[reindex] - a[index];
dis[index] = dis[reindex] + 1;
for (int i = head[index], temp = 0; i != 0; i = nex[i]) {
if (w[i] == reindex) continue;
if (temp++ == 0) dfs(w[i], index, top);
else dfs(w[i], index, w[i]);
}
return;
}
int lca(int x, int y){
while (node[x] != node[y]) {
if (dis[node[x]] < dis[node[y]]) swap(x, y);
x = fa[node[x]];
}
if (dis[x] < dis[y]) return x;
else return y;
}
int main() {
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int n, m; cin >> n >> m;
for (int i = 1; i <= n; i++) cin >> a[i];
for (int i = 1; i < n; i++) {
int x, y; cin >> x >> y;
add(x, y);
add(y, x);
}
dfs(1, 0, 1);
while (m--) {
int x, y; cin >> x >> y;
int index = lca(x, y);
cout << a[x] + reload[x] - reload[index] + load[y] - load[index] << "\n";
}
}
I.小沙的构造
思路
构造,大体思想很好想,一些细节处理比较麻烦~~(因为我太菜了~~
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
string arr = "\"!'*+-.08:=^_WTYUIOAHXVM|<>\\/[]{}()";
int main() {
int n, m; cin >> n >> m;
if (m == 36 || m > n || (m >= 10 && ((n - 10 + 1) / 2 < (m - 10))) ) {
cout << -1;
return 0;
}
if (m & 1) {
if (m <= 11) {
for (int i = 25; i <= 23 + m - 1; i += 2) cout << arr[i];
for (int i = 1; i <= n - m + 1; i++) cout << arr[0];
for (int i = 24 + m - 1; i > 25; i -= 2) cout << arr[i];
}
else {
for (int i = 25; i < 35; i += 2) cout << arr[i];
for (int i = 1; i <= m - 11; i++) cout << arr[i];
for (int i = 1; i <= n - 10 - 2 * (m - 11); i++) cout << arr[0];
for (int i = m - 11; i >= 1; i--) cout << arr[i];
for (int i = 34; i > 25; i -= 2) cout << arr[i];
}
}
else {
if (m <= 12) {
if (n & 1) {
int temp = 0;
for (int i = 25; i <= min(33, 23 + m - 1); i += 2, temp++) cout << arr[i];
cout << arr[0];
for (int i = 1; i <= n - 2 * temp - 2; i++) cout << arr[1];
cout << arr[0];
for (int i = min(34, 24 + m - 2); i > 25; i -= 2) cout << arr[i];
}
else {
int tmep = m;
for (int i = 25; i <= min(33, 23 + m); i += 2, tmep -= 2) cout << arr[i];
if (tmep > 0) {
for (int i = 1; i <= tmep; i++) cout << arr[i - 1];
for (int i = 1; i <= n - 10 - 2 * (m - 10); i++) cout << arr[tmep - 1];
for (int i = tmep; i >= 1; i--) cout << arr[i - 1];
}
else {
for (int i = 1; i <= (n - m) / 2; i++) cout << arr[23 + m];
for (int i = 1; i <= (n - m) / 2; i++) cout << arr[24 + m];
}
for (int i = min(34, 24 + m); i > 25; i -= 2) cout << arr[i];
}
}
else {
for (int i = 25; i < 35; i += 2) cout << arr[i];
for (int i = 0; i < m - 10; i++) cout << arr[i];
for (int i = 1; i <= n - 10 - 2 * (m - 10); i++) cout << arr[0];
for (int i = m - 11 - (n - 10 - 2 * (m - 10) < 0); i >= 0; i--) cout << arr[i];
for (int i = 34; i > 25; i -= 2) cout << arr[i];
}
}
}