牛客小白月赛73
A.最小的数字
题目:
分析:
简单枚举一下,找到第一个大于等于n的且是3的倍数的数
代码:
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin >> n;
bool loop = true;
if (n % 3 == 0)
loop = false;
while (loop)
{
n ++;
if (n % 3 == 0)
loop = false;
}
cout << n;
return 0;
}
B.优美的GCD
题目:
分析:
根据题目条件,用两个质数分别乘以n即可构造出答案。
代码:
#include <bits/stdc++.h>
using namespace std;
int main()
{
std::ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t;
cin >> t;
while (t --)
{
int n;
cin >> n;
cout << n * 2 << " " << n * 3 << endl;
}
return 0;
}
C.优美的序列
题目:
分析:
如果序列中存在相同项,由于下标差值最小是1,所以无解。
如果序列中不存在相同项,不妨对序列从小到大排序,由于两两各不相同,因此任意相邻两项的差的绝对值都至少是1,对任意1 <= i,j <= n都有|ai - aj| >= |i - j|成立
代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
int a[N];
int main()
{
std::ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t;
cin >> t;
while (t --)
{
int n;
cin >> n;
unordered_map<int, bool> mp;
unordered_map<int, int> mp2;
bool check = false;
for (int i = 0; i < n; i ++)
{
cin >> a[i];
if (mp[a[i]])
check = true;
mp[a[i]] = true;
}
if (check)
cout << -1 << endl;
else
{
sort(a, a + n);
for (int i = 0; i < n; i ++)
cout << a[i] << " ";
cout << endl;
}
}
return 0;
}
D/E Kevin喜欢零
题目:
分析:
hard版本:
x的末尾恰好有k个0,则x = p×10k = p×2k×5k且p与10互质,换句话说,设x中2的因子数位a, 5的因子数位b,当且仅当min(a, b) = k使得x的末尾恰好有k个0。因此,判断一个区间内元素的累乘结果是否恰好有k个0,即看min(区间内因子2的总数,区间内因子5的总数)是否为k,这个查询判断可以用前缀和来做。接着就是枚举有多少个满足此要求的区间。枚举区间我们可以采用固定一个端点然后枚举另一个端点的方式。不妨固定左端点,枚举右端点,由于我们统计的因子数量是非递减的,因此可以二分右端点,设对于因子2的数量等于k的区间是[l2,r2],因子5的数量等于k的区间是[l5,r5],由于右端点的位置要满足所选区间最小值是k,因此右端点的选择范围是[max(l2,l5), max(r2,r5)]。最后统计所有满足条件的区间数量即可。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 5;
int a[N];
LL s2[N], s5[N];
int main()
{
std::ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t;
cin >> t;
while (t --)
{
int n, k;
cin >> n >> k;
for (int i = 0; i <= n; i ++)
{
s2[i] = s5[i] = 0;
}
for (int i = 1; i <= n; i ++)
{
cin >> a[i];
int m = a[i];
while (m % 2 == 0)
{
s2[i] ++;
m /= 2;
}
m = a[i];
while (m % 5 == 0)
{
s5[i] ++;
m /= 5;
}
s2[i] += s2[i - 1];
s5[i] += s5[i - 1];
}
LL res = 0;
for (int i = 1; i <= n; i ++)
{
LL t2 = s2[i - 1] + k, t5 = s5[i - 1] + k;
int l2 = lower_bound(s2, s2 + n + 1, t2) - s2, r2 = upper_bound(s2, s2 + n + 1, t2) - s2 - 1;
int l5 = lower_bound(s5, s5 + n + 1, t5) - s5, r5 = upper_bound(s5, s5 + n + 1, t5) - s5 - 1;
int l = max(l2, l5), r = max(r2, r5);
l = max(i, l); // 避免l枚举到i的左边
if (l == n + 1) // l为n + 1则说明没有满足条件的右端点
continue;
res += r - l + 1;
}
cout << res << endl;
}
return 0;
}
Kevin的哈希构造
题目:
分析:
考虑dp。定义f[i][j][k]为前i个字符中有j个相同项且字符串哈希值为k的方案是否可行。
初始:f[0][0][0] = 1
转移:
①可以考虑用前面的值来推当前:f[i][j][k] |= f[i - 1][j - (s[i] == c)][(k - (c - 'a' + 1) × bi + p) % p]
②也可以考虑用当前的值来推后面的值:f[i + 1][j + (s[i] == c)][(k × b + (c - 'a' + 1)) % p] |= f[i][j][k]
本人选择的是第二种方式。
目标状态: f[n][k][hash]
至于记录方案则可以用一个pre_h数组记录上一个方案的哈希值以及ch数组记录当前方案的选择的字符。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 55, M = 1010;
bool f[N][N][M];
LL pre_h[N][N][M];
char ch[N][N][M], s[N];
int main()
{
std::ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t;
cin >> t;
while (t --)
{
int n, p, k;
LL b, H = 0;
cin >> n >> b >> p >> k;
cin >> s + 1;
memset(f, false, sizeof f);
f[0][0][0] = true;
for (int i = 1; i <= n; i ++)
H = (H * b + s[i] - 'a' + 1) % p;
for (int i = 0; i <= n; i ++)
{
for (int j = 0; j <= min(i, k); j ++)
{
for (int l = 0; l < p; l ++)
{
if (f[i][j][l])
{
for (char c = 'a'; c <= 'z'; c ++)
{
LL h2 = (l * b + (c - 'a' + 1)) % p;
if (s[i + 1] == c)
{
f[i + 1][j + 1][h2] = true;
pre_h[i + 1][j + 1][h2] = l;
ch[i + 1][j + 1][h2] = c;
}
else
{
f[i + 1][j][h2] = true;
pre_h[i + 1][j][h2] = l;
ch[i + 1][j][h2] = c;
}
}
}
}
}
}
if (!f[n][k][H])
cout << -1 << endl;
else
{
string res;
for (int i = n, j = k, h2 = H; i >= 1; i --)
{
res += ch[i][j][h2];
int tmp = h2;
h2 = pre_h[i][j][h2];
if (s[i] == ch[i][j][tmp])
j --;
}
reverse(res.begin(), res.end());
cout << res << endl;
}
}
return 0;
}
G.MoonLight的冒泡排序难题
题目:
分析:
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 5, mod = 998244353;
LL f[N];
LL qmi(LL m, LL k)
{
LL res = 1, t = m;
while (k)
{
if (k & 1)
res = res * t % mod;
t = t * t % mod;
k >>= 1;
}
return res;
}
int main()
{
std::ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
for (int i = 1; i <= N; i ++)
{
f[i] = (f[i - 1] + (i - 1) * qmi(i, mod - 2)) % mod;
}
int t;
cin >> t;
while (t --)
{
int n;
cin >> n;
cout << f[n] << endl;
}
return 0;
}