牛客周赛55
A 小红的字符串
小红拿到了一个长度为
void solve() {
string s;cin >> s;
set<char>ss;
for (auto x : s)ss.insert(x);
cout << ss.size() - 1 << '\n';
}
B 小红的序列乘积
小红有一个长度为
void solve() {
int n;cin >> n;
int cnt = 0, mul = 1;
for (int i = 1;i <= n;i++) {
int x;cin >> x;
mul *= x % 10;mul %= 10;
if (mul == 6)cnt++;
}
cout << cnt << '\n';
}
C 小红的数组重排
给出一个数字
显然,直接排序即可
若出现三个相同的数字,则,就不满足要求了
若出现 2 个 0,则,前一个式子和后一个式子的结果都为 0,也不满足要求。
void solve() {
int n;cin >> n;
vector<int> a(n + 1);map<int, int>mp;
for (int i = 1;i <= n;i++)cin >> a[i], mp[a[i]]++;
for (auto [x, y] : mp) {
if (y >= 3) {
cout << "NO\n";return;
}
}
if (mp[0] >= 2) {
cout << "NO\n";return;
}
cout << "YES\n";
sort(a.begin() + 1, a.end());
for (int i = 1;i <= n;i++)cout << a[i] << " \n"[i == n];
}
D 虫洞操纵者
你需要在一个可以上下左右移动的
别人都不知道的是,你是一个虫洞大师,当你所在的位置能同时看到左右两侧或上下两侧最近的那两面相对的墙时,你可以在这两面墙上开启虫洞,靠近后从一侧进入,穿越它到达另一侧。
现在,你准备好以最短的步数离开迷宫了吗!
普通 BFS+特殊处理,遇到墙了之后反方向移动直到遇到另外一个墙即可
int s[1010][1010], vis[1010][1010];
int dx[] = {0,0,1,-1};
int dy[] = {1,-1,0,0};
void solve() {
int n;cin >> n;
for (int i = 1;i <= n;i++) {
for (int j = 1;j <= n;j++) {
cin >> s[i][j];
}
}
for (int i = 1;i <= n;i++) {
s[0][i] = 1;
s[i][0] = 1;
s[n + 1][i] = 1;
s[i][n + 1] = 1;
}
queue<tuple<int, int, int>>q;q.push({1,1,0});
vis[1][1] = 1;
while (q.size()) {
auto [x, y, step] = q.front();q.pop();
if (x == n && y == n) {
cout << step << '\n';return;
}
for (int i = 0;i < 4;i++) {
int a = x + dx[i], b = y + dy[i];
if (vis[a][b])continue;
if (!s[a][b]) {
vis[a][b] = 1;q.push({a,b,step + 1});
} else {
int dirx = -1, diry = -1;
for (int j = 0;j < 4;j++) {
if (dx[j] == -dx[i] && dy[j] == -dy[i]) {
dirx = dx[j], diry = dy[j];
}
}
a += dirx, b += diry;
while (!s[a][b]) {
a += dirx, b += diry;
}
a -= dirx, b -= diry;
if (!vis[a][b]) {
vis[a][b] = 1;q.push({a,b,step + 1});
}
}
}
}
cout << "-1\n";
}
E 小红的序列乘积 2.0
对于一个长度为
小红有一个长度为
Solution
DP
设
当前状态一定是包含了之前的状态的,即
当前数字为
当加入当前数字后,以 6 结尾了,满足要求,设该子序列为
#define int long long
constexpr int mod = 1e9 + 7;
void solve() {
int n;cin >> n;
vector<int> a(n + 1);
for (int i = 1;i <= n;i++) {
cin >> a[i];a[i] %= 10;
}
vector<array<int, 10>> f(n + 1);//代表前i个数字有多少种以j结尾的方案数
f[0][1] = 1;
int ans = 0;
for (int i = 1;i <= n;i++) {
for (int j = 0;j < 10;j++) {
if (j * a[i] % 10 == 6) {
ans += f[i - 1][j] * qpow(2, n - i) % mod;ans %= mod;
}
f[i][j] += f[i - 1][j];f[i][j] %= mod;
f[i][j * a[i] % 10] += f[i - 1][j];f[i][j * a[i] % 10] %= mod;
}
}
cout << ans << '\n';
}
F 的计算几何暗示我该学习计算几何了!