怀化学院2024年ACM基地第二轮招新机试题解

比赛地址:https://www.nowcoder.com/acm/contest/96304。【邀请码:acm20241115】

A

宋学长买书

#include 
#define int long long

const int N=1e6+10;
int a[N];

int min(int a,int b)
{
	if(a<=b) return a;
	return b;
}

signed main()
{
	int T;
	scanf("%lld",&T);
	while(T--)
	{
		int n,m;
		scanf("%lld %lld",&n,&m);
		int cnt=0,pl=1e18,ans=0;
		for(int i=0;i=m) pl=min(pl,x);
			else ans+=x,cnt++;
		}
		ans+=pl-1;
		if(cnt>m) 
			printf("Impossible\n");
			
		else
		{
			if(ans>=1e18-1) printf("Richman\n");
			else printf("%lld\n",ans);
		}
	}
	return 0;
}
B 山谷

// 第i行第j列处于的对角线可以由j - i + n - 1表示
// https://codeforces.com/contest/2033/problem/B 900
#include 
using namespace std;
#define int long long
#define endl '\n'
#define pii pair
const int N = 1E5 + 10;
const int mod = 998244353;
int mp[1000][1000];
void solve()
{
    int n;
    cin >> n;
    vector frow(10 * n, 1e9);
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            cin >> mp[i][j];
            int x = j - i + n - 1;
            frow[x] = min(frow[x], mp[i][j]);
        }
    }
    int res = 0;
    for (int i = 0; i < 2 * n - 1; i++)
        res += max((int)0, -frow[i]);
    cout << res << endl;
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    int t = 1;
    cin >> t;
    while (t--)
        solve();
}
C 也许是字符串排序?

// 统计区间每个字符的数量计算差值就好了
// https://codeforces.com/contest/1996/problem/C 1200
#include 
using namespace std;
#define int long long
#define endl '\n'
const int N = 2e5 + 10;
const int mod = 1e9 + 7;
int s1[N][30];
int s2[N][30];
void solve()
{
    int n, q;
    cin >> n >> q;
    string a, b;
    cin >> a >> b;
    a = ' ' + a;
    b = ' ' + b;
    for (int i = 1; i <= n; i++)
    {
        for (int j = 0; j < 30; j++)
            s1[i][j] = 0, s2[i][j] = 0;
    }

    for (int i = 1; i <= n; i++)
    {
        int t1 = a[i] - 'a';
        int t2 = b[i] - 'a';
        for (int j = 0; j < 26; j++)
        {
            s1[i][j] = s1[i - 1][j];
            s2[i][j] = s2[i - 1][j];
        }
        s1[i][t1]++;
        s2[i][t2]++;
    }
    while (q--)
    {
        int l, r;
        cin >> l >> r;
        int cnt = 0;
        for (int i = 0; i < 26; i++)
        {
            int t1 = s1[r][i] - s1[l - 1][i];
            int t2 = s2[r][i] - s2[l - 1][i];
            cnt += abs(t1 - t2);
        }
        cout << cnt / 2 << endl;
    }
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t;
    cin >> t;
    while (t--)
        solve();
}
D 数组操作

#include 
#define int long long


signed main()
{
	int n;
	scanf("%lld",&n);
	int sum=0;
	for(int i=0;i
E 增加/减少/复制

// 关键点在于处理最后一个数字上,判断最后一个数字是否出现过,出现过就不需要加上权值,否则加上最小的需要操作的次数
// https://codeforces.com/contest/1976/problem/B
#include 
using namespace std;
#define int long long
#define endl '\n'
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
void solve()
{
    int n;
    cin >> n;
    vector a(n);
    for (int &x : a)
        cin >> x;
    vector b(n + 1);
    for (int &x : b)
        cin >> x;
    int res = 0;
    bool is = false;
    int mini = 1e17;
    for (int i = 0; i < n; i++)
    {
        int t = abs(a[i] - b[i]);
        res += t;
        int l = min(a[i], b[i]);
        int r = max(a[i], b[i]);
        mini = min(mini, abs(l - b[n]));
        mini = min(mini, abs(r - b[n]));
        if (b[n] >= l && b[n] <= r)
            is = true;
    }
    res++;
    if (is == false)
        res += mini;
    cout << res << endl;
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t;
    cin >> t;
    while (t--)
        solve();
}
F 三维坐标中的计算几何

防ak题,详见D - Country Meow-CSDN博客

G

下棋

// 贪心匹配,只要s合法(即至少存在一个01),那么我们就将t中的1与s的0抵消(即将01换成1)、t的0与s的1抵消。当无法抵消时(即s中不存在需要的0或1)就输出NO,都能抵消完就输出YES
// https://codeforces.com/contest/2029/problem/B 1100
#include 
using namespace std;
#define all(s) s.begin(), s.end()
#define int long long
#define endl '\n'
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
void solve()
{
    int n;
    cin >> n;
    string s, t;
    cin >> s >> t;
    int cnt0 = 0, cnt1 = 0;
    for (int i = 0; i < n; i++)
    {
        if (s[i] == '0')
            cnt0++;
        else
            cnt1++;
    }
    for (int i = 0; i < n - 1; i++)
    {
        if (cnt0 <= 0 || cnt1 <= 0)
        {
            cout << "NO" << endl;
            return;
        }
        if (t[i] == '0')
            cnt1--;
        else
            cnt0--;
    }
    cout << "YES" << endl;
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t;
    cin >> t;
    while (t--)
        solve();
}
H 实现相等

// 魔法只能用一次,判断用在数组前面还是数组后面哪个更赚就行了(特殊情况能用在中间)
// https://codeforces.com/contest/1931/problem/C 1000
#include 
using namespace std;
#define int long long
#define endl '\n'
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
void solve()
{
    int n;
    cin >> n;
    vector v(n);
    for (int i = 0; i < n; i++)
    {
        cin >> v[i];
    }
    int l = 0;
    int r = n - 1;
    while (l < n && v[l] == v[0])
        l++;
    if (l == n)
    {
        cout << 0 << endl;
        return;
    }
    while (r >= 0 && v[r] == v[n - 1])
        r--;
    l--, r++;
    if (v[l] == v[r])
    {
        cout << r - l - 1 << endl;
        return;
    }
    if (l + 1 >= n - r)
        cout << n - l - 1 << endl;
    else
        cout << r << endl;
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t;
    cin >> t;
    while (t--)
        solve();
}
I 迷雾(easy)
// q<=500,直接暴力模拟就行
// https://www.luogu.com.cn/problem/P11078
#include 
using namespace std;
#define int long long
#define endl '\n'
const int N = 1e3 + 10;
const int mod = 1e9 + 7;
int n, m, q, k;
char mp[N][N];
int op[N * 1000];

char change(char x)
{
    if (x == 'U')
        return 'D';
    if (x == 'D')
        return 'U';
    if (x == 'L')
        return 'R';
    if (x == 'R')
        return 'L';
    return ' ';
}
void solve()
{
    cin >> n >> m >> q >> k;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++)
            cin >> mp[i][j];
    int x = 1, y = 1;
    for (int i = 1; i <= q; i++)
    {
        char c;
        int a, b;
        cin >> c >> a >> b;
        if (op[i] % 2 == 1)
            c = change(c);
        if (c == 'U')
            x = max(1ll, x - a);
        if (c == 'D')
            x = min(n, x + a);
        if (c == 'L')
            y = max(1ll, y - a);
        if (c == 'R')
            y = min(m, y + a);
        if (mp[x][y] == 'X')
            for (int j = i + k; j <= q && j <= i + b * k; j += k)
                op[j]++;
    }
    cout << x << " " << y << endl;
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t = 1;
    // cin >> t;
    while (t--)
        solve();
}
J 迷雾(hard)

// q<=6E5,但是k<=25,开25个差分数组维护就好了
// https://www.luogu.com.cn/problem/P11078
#include 
using namespace std;
#define int long long
#define endl '\n'
const int N = 1e3 + 10;
const int mod = 1e9 + 7;
int n, m, q, k;
char mp[505][505];
int op[200020][30]; // k最大为25,开25个差分数组维护需要修改的区间
int vel[30];        // 当前余数为i%k时的操作状态
// 遍历1到q个操作,对于当前操作i可以表示成 i%k+(i/k)*k,可以在op数组中表示成 op[i/k][i%k]
// 假设当前走到了迷雾需要进行后续的修改操作,那么需要修改的操作区间为op[i/k+1][i%k]到op[i/k+1+b][i%k]
// 这样就将分段的操作区间映射成了一个连续区间,直接差分数组维护就好了
char change(char x)
{
    if (x == 'U')
        return 'D';
    if (x == 'D')
        return 'U';
    if (x == 'L')
        return 'R';
    if (x == 'R')
        return 'L';
    return ' ';
}
void solve()
{
    cin >> n >> m >> q >> k;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++)
            cin >> mp[i][j];
    int x = 1, y = 1;
    for (int i = 1; i <= q; i++)
    {
        char c;
        int a, b;
        cin >> c >> a >> b;
        vel[i % k] += op[i / k][i % k];
        if (vel[i % k] % 2)
            c = change(c);
        if (c == 'U')
            x = max(1ll, x - a);
        if (c == 'D')
            x = min(n, x + a);
        if (c == 'L')
            y = max(1ll, y - a);
        if (c == 'R')
            y = min(m, y + a);
        if (mp[x][y] == 'X')
        {
            op[i / k + 1][i % k] += 1;
            op[i / k + 1 + b][i % k] -= 1;
        }
    }
    cout << x << " " << y << endl;
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t = 1;
    // cin >> t;
    while (t--)
        solve();
}
K 打印矩形螺旋图案

#include 
using namespace std;

int main()
{
    int n;
    cin >> n;         // 输入矩阵的大小
    int matrix[n][n]; // 定义一个 n x n 的二维数组
    int left = 0, right = n - 1, top = 0, bottom = n - 1;
    int num = 1;

    while (left <= right && top <= bottom)
    {
        // 填充上边
        for (int i = left; i <= right; i++)
        {
            matrix[top][i] = num++;
        }
        top++;

        // 填充右边
        for (int i = top; i <= bottom; i++)
        {
            matrix[i][right] = num++;
        }
        right--;

        // 填充下边
        if (top <= bottom)
        {
            for (int i = right; i >= left; i--)
            {
                matrix[bottom][i] = num++;
            }
            bottom--;
        }

        // 填充左边
        if (left <= right)
        {
            for (int i = bottom; i >= top; i--)
            {
                matrix[i][left] = num++;
            }
            left++;
        }
    }

    // 打印矩阵
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            cout << matrix[i][j] << " ";
        }
        cout << endl;
    }

    return 0;
}
L 哥德巴赫猜想

#include 
#define int long long

const int N=50010;
int v[N],cnt;
int st[N];

void is()
{
	for(int i=2;i<50010;i++)
	{
		int flag=1;
		for(int j=2;j<=i/j;j++)
			if(i%j==0)
			{
				flag=0;
				break;
			}
		if(flag) 
		{
			v[cnt++]=i;
			st[i]=1;
		}
	}
}

void solve()
{
	int x;
	scanf("%lld",&x);
	int f=0;
	for(int i=0;i

你可能感兴趣的:(算法)