蒟蒻第一次写题解,如若有不好的地方见谅~
算法交流群QQ:891869943 欢迎进来一起玩~
A
按照题意直接写即可
检测字符串是否为 "kou"就行
void work(){
string s; cin >> s;
if(s == "kou") s = "yukari";
cout << s << '\n';
}
B
分解质因子,同时统计数量即可
void work(){
cin >> n;
ll res = 0;
for(int i = 2; i <= n / i; i++){
if(n % i == 0){
res++;
while(n % i == 0) n /= i;
}
}
if(n > 1) res++;
cout << res << '\n';
}
C
枚举字符即可
容易发现,每个字符作为中值的字符串数量取决于它左右两边的长度的最小值
void work(){
cin >> n >> c;
string s; cin >> s;
ll res = 0;
for(ll i = 0; i < n; i++){
if(s[i] == c){
res += min(i + 1, n - i);
}
}
cout << res << '\n';
}
D
模拟链表操作即可
const int N = 2e5 + 10;
ll n;
int idx = 0;
int l[N], r[N]; //左指针,右指针
map<int, int> id; //每个值的索引
int a[N]; //索引对应的值
void work(){
cin >> n;
int op, x, y;
int sz = 0; //值的数量
while(n--){
cin >> op;
if(op == 1){
cin >> x >> y;
id[x] = ++idx; //为值生成索引
a[idx] = x;
int p = id[y];
r[idx] = r[p];
l[r[p]] = idx;
r[p] = idx;
l[idx] = p;
sz++;
}else{
cin >> x;
int p = id[x];
r[l[p]] = r[p];
l[r[p]] = l[p];
sz--;
}
}
cout << sz << '\n';
int p = r[0]; //使p指向第一个值的索引
while(p != 0){
cout << a[p] << " ";
p = r[p];
}
cout << '\n';
}
E
看到题目,我们很容易想到01背包
我们分两个背包:正数背包f1, 负数背包f2。将背包初始化为1e9(表示不可到达)
假设sum为所有值的和。
如果sum > 0, 说明我们需要将一些正整数乘以 -1, 此时就查询正数背包。反之亦然
此外,我们还发现,乘以-1后给sum带来的变化是2倍的,说明如果sum为奇数则无解,并且查询背包时要先除以2.
const int N = 4e4 + 10;
ll n;
int f1[N], f2[N]; //背包
void work(){
cin >> n;
//40000是最大值
for(int i = 1; i <= 40000; i++) f1[i] = f2[i] = 1e9;
f1[0] = f2[0] = 0;
ll sum = 0;
for(int i = 1; i <= n; i++){
int x; cin >> x;
sum += x;
if(x > 0) {
for(int v = 40000; v >= x; v--) {
if(f1[v - x] != -1)
f1[v] = min(f1[v], f1[v - x] + 1);
}
}
else if(x < 0) {
for(int v = 40000; v >= -x; v--) {
if(f2[v + x] != -1)
f2[v] = min(f2[v], f2[v + x] + 1);
}
}
}
//奇数则无解
if(sum & 1){
cout << -1 << '\n';
return;
}
sum /= 2;
if(sum > 0) cout << (f1[sum] == 1e9 ? -1 : f1[sum]) << '\n';
else cout << (f2[sum] == 1e9 ? -1 : f2[sum]) << '\n';
}
F
假设x比y小
我们把a, b分开来看,假设 x 个 a 被分为 u 个部分, y 个 b 被分为 v 个部分
相当于 x - 1 个空隙中插入 u - 1 个挡板将 a 分成 u 个部分,则不同数量为
例如7个 a 被分为 4 个部分 -> 相当于 6 个空隙中插入 3 个挡板
我们每次只需要将 a 和 b 的不同数量相乘起来就行
注意到如果 i = 1 或者 i > 2 * x + 1时,答案为0。(x为较小的数),因为此时无法形成连续段为 i 的字符串。
此外还要分两种情况,一种是以 a 为开头, 一种是以 b 为开头。(需要判断符合条件)
const int N = 1e3 + 100;
const int mod = 1e9 + 7;
ll n;
ll c[N][N]; //组合数
void work(){
ll x, y; cin >> x >> y;
//预处理组合数
for(int i = 0; i <= 1011; i++){
for(int j = 0; j <= i; j++){
if(j == 0) c[i][j] = 1;
else c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod;
}
}
if(x > y) swap(x, y); //让x成为较小的数
for(int i = 1; i <= x + y; i++){
if(i < 2 || i > 2 * x + 1){
cout << 0 << '\n';
continue;
}
ll res = 0;
ll u = i / 2 + (i & 1), v = i / 2; //分为u部分和v部分
//只有 >=u 才能放在开头
if(y >= u) res = (res + c[y - 1][u - 1] * c[x - 1][v - 1] % mod) % mod;
if(x >= u) res = (res + c[x - 1][u - 1] * c[y - 1][v - 1] % mod) % mod;
cout << res << '\n';
}
}