B. Find The Array
题意:满足b[]数组中相邻的两个数大的能被小的整除。且a中元素与b总元素差值总和的两倍小于等与a中元素的总和。
我们知道a1,1,a3, 1,a5,1…或1,a2,1,a4…这样的数组能满足第一个要求。我们要证明是否满足第二个要求。我们取一个总和大的数列s’,已知a1+a2+a3+a4…=s,所以s’>s/2,a[]数组减去他一定满足第二个要求。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int t, n;
ll a[55], b[55];
int main()
{
scanf("%d", &t);
while (t -- )
{
scanf("%d", &n);
ll eve = 0, odd = 0;
for (int i = 1; i <= n; i ++ )
{
scanf("%lld", &a[i]);
if (i & 1) odd += a[i];
else eve += a[i];
}
if (odd > eve)
{
for (int i = 1; i <= n; i ++ )
{
if (i & 1) cout << a[i] << ' ';
else cout << '1' << ' ';
}
puts("");
}
else
{
for (int i = 1; i <= n; i ++ )
{
if (i & 1) cout << '1' << ' ';
else cout << a[i] << ' ';
}
puts("");
}
}
return 0;
}
D. Add to Neighbour and Remove
题意:一个数可以和他旁边的两个数相加,经历过最小的操作数后,数组里的每个值都相同。
因为n=3000,可以大胆暴力。
设最后剩下k个元素,则每个值为sum/k,遍历整个数组,如小于平均值,则加上下一个值,如果大于平均值了,则用下一个方法。
#include <bits/stdc++.h>
using namespace std;
const int N = 30030;
typedef long long ll;
vector <ll> a(N);
int main()
{
int t, n;
cin >> t;
while (t -- )
{
scanf("%d", &n);
ll sum = 0;
for (int i = 1; i <= n; i ++ )
{
scanf("%lld", &a[i]);
sum += a[i];
}
ll ave;
for (int i = n; i >= 1; i -- )
{
bool f = 1;
if (sum % i == 0)
{
ave = sum / i;
ll cursum = 0;
for (int j = 1; j <= n; j ++ )
{
cursum += a[j];
if (cursum > ave)
{
f = 0;
break;
}
else if (cursum == ave) cursum = 0;
}
if (f)
{
printf("%d\n", n - i);
break;
}
}
}
}
return 0;
}
Trie字符串统计打卡
#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
int son[N][26], cnt[N], idx;
char str[N];
void insert(char str[])
{
int p = 0;
for (int i = 0; str[i]; i ++ )
{
int u = str[i] - 'a';
if (!son[p][u]) son[p][u] = ++ idx;
p = son[p][u];
}
cnt[p] ++;
}
int query(char str[])
{
int p = 0;
for (int i = 0; str[i]; i ++ )
{
int u = str[i] - 'a';
if (!son[p][u]) return 0;
p = son[p][u];
}
return cnt[p];
}
int main()
{
int n;
scanf("%d", &n);
while (n -- )
{
char op[2];
scanf("%s%s", op, str);
if (*op == 'I') insert(str);
else printf("%d\n", query(str));
}
return 0;
}
以后尽量在课较少的时候,能完成2道cf上的题,学两个模板题。