D题不会双链表,在网上找到一个板子,直接用了现在还没学。

E题赛时用全排列骗了点分,感觉会是 ,但没有想出来。

F题不会,也没想补。

A-小红小紫替换

签到题

#include<bits/stdc++.h>
using namespace std;
const int N =101001;

int n,m,ans;
int main ()
{
    string s;
    cin>>s;
    if(s=="kou")cout<<"yukari";
    else cout<<s;
       return 0;
}

B-小红质因子数

分解质因数,注意开

#include <bits/stdc++.h>
using namespace std;
long long n;
long long ans = 0;
void divide(long long  x)
{
	for (long long  i = 2; i <= x / i; i++)
	{
		if (x % i == 0)
		{
			while (x % i == 0)
                x /= i;
			++ans;
		}
	}
	if (x > 1)
		++ans;
	cout << ans;
	return;
}
int main()
{
	cin >> n;
	if (n == 1)
	{
		cout << 0;
		return 0;
	}
	divide(n);
	return 0;
}

C-小红的字符串中值

自身算一种。

以自身为中值,扩展到边界,取最先到达的边界。

#include<bits/stdc++.h>
using namespace std;
const int N =101001;
char a[N];
char s;
int n,m,ans;
int main ()
{
	cin>>n>>s;
	cin>>a+1;
	for(int i=1;i<=n;i++)
	{
          if(a[i]==s){
			++ans;
			int k=min(i-1,n-i);
			ans+=k;
		  }
	}
	cout<<ans;
	   return 0;
}

D-小红的数组操作

显然这是个对数组本身要满足 增删操作。

所以要用链表,由题意可知要用双向链表。

由于数据的空间限制,需要考虑用到离散化。

#include <bits/stdc++.h>
using namespace std;
const int N = 200010;
int m, ans, M, t;
int v[N];
int a[N];
int e[N], l[N], r[N], idx;
struct nihao
{
	int x, y;
	int k;
} p[N];
// 在节点a的右边插入一个数x
void insert(int a, int x)
{
	e[idx] = x;
	l[idx] = a, r[idx] = r[a];
	l[r[a]] = idx, r[a] = idx++;
}
// 删除节点a
void remove(int a)
{
	l[r[a]] = l[a];
	r[l[a]] = r[a];
}
int main()
{
	cin >> m;
	// 0是左端点,1是右端点
	r[0] = 1, l[1] = 0;
	idx = 2;
	for (int i = 1; i <= m; i++)
	{
		int op;
		cin >> op;
		int x = 0, y = 0;
		if (op == 1)
		{
			cin >> x >> y;
			a[++t] = x;
		}
		else
			cin >> x;
		p[i].k = op;
		p[i].x = x;
		p[i].y = y;
	}
	sort(a + 1, a + 1 + t);
	for (int i = 1; i <= m; i++)
	{
		int x = p[i].x;
		int mm = lower_bound(a + 1, a + t + 1, x) - a;
		if (p[i].k == 1)
		{
			int y = p[i].y;

			int nn = lower_bound(a + 1, a + t + 1, y) - a;
			v[mm] = ++ans;
			if (y == 0)
				insert(0, x);
			else
				insert(v[nn] + 1, x);
		}
		else
			remove(v[mm] + 1);
	}
	for (int i = r[0]; i != 1; i = r[i])
		++M;
	cout << M << "\n";
	for (int i = r[0]; i != 1; i = r[i])
		cout << e[i] << ' ';
	return 0;
}

E-小红的子集取反

开始看到不知道何从下手,考虑用的全排列,对于每 个数进行 的操作,枚举 进行搜索。

在搜索的时候,加一个变量,用来判断时间来骗分。

过了 的数据。

骗分代码

#include <bits/stdc++.h>
using namespace std;
const int N = 101001;
int a[N];
int b[N];
int n;
int v[N], ans[N];
int Ans;
int flag;
void dfs(int m, int k)
{
	++Ans;
	if (Ans == 10000008)
	{
		cout << -1;
		exit(0);
	}
	if (m > k)
	{
		for (int i = 1; i <= k; i++)
			a[ans[i]] *= -1;
		int s = 0;
		for (int i = 1; i <= n; i++)
			s += a[i];
		if (s == 0)
		{
			flag = 1;
		}
		for (int i = 1; i <= k; i++)
			a[ans[i]] *= -1;
		return;
	}
	for (int i = 1; i <= n; i++)
	{
		if (!v[i])
		{
			ans[m] = i;
			v[i] = 1;
			dfs(m + 1, k);
			if (flag == 1)
				return;
			v[i] = 0;
		}
	}
	return;
}
int main()
{
	cin >> n;
	for (int i = 1; i <= n; i++)
		cin >> a[i], b[i] = a[i];
	for (int k = 0; k <= n; k++)
	{
		for (int i = 1; i <= n; i++)
			a[i] = b[i];
		dfs(1, k);
		if (flag == 1)
		{
			cout << k;
			return 0;
		}
	}
	cout << -1;
	return 0;
}

正解就是 了,主要没往 方程这里想,想到了自然就可以写出来了。

表示在 位置和为 时最小的操作次数。

方程转移 :

操作的时候对于负数情况,对整个数组进行一个偏移即可。

#include <bits/stdc++.h>
using namespace std;
const int N = 101001;
int f[201][120000];
int a[N];
int M = 40000;
int n, m, ans;
int main()
{
    cin >> n;
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    for (int j = -M; j <= M; j++)
        f[0][j + M] = N;
    f[0][M] = 0;
    for (int i = 1; i <= n; i++)
    {
        for (int j = -M; j <= M; j++)
        {
            f[i][j + M] = min(f[i - 1][j + M - a[i]], f[i - 1][j + M + a[i]] + 1);
        }
    }
    if (f[n][M] != N)
        cout << f[n][M];
    else
        cout << -1;
    return 0;
}