A题
给出n,k,求三个数x/y/z,使得n = x + y + z,并且gcd(x,y) = gcd(x,z) = gcd(y,z) = k
解:在n / k / 3范围内左右查找符合条件的值

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
ll t,n,k;

int solve()
{
    if(n % k) return 0;
    ll p = n / k;
    ll r = p / 3;
    for(ll i = max(2LL,r - 100);i <= min(p,r + 100); ++i)
        for(ll j = max(2LL,r - 100);j <= min(p,r + 100); ++j)
        {
            if(p - i - j <= 1 || __gcd(i,j) != 1 || __gcd(i,p - i - j) != 1 || __gcd(j,p - i - j) != 1) continue;
            cout<<i * k<<' '<<j * k<<' '<<(p - i - j) * k<<'\n';
            return 1;
        }
    return 0;
}

int main()
{
    std::ios::sync_with_stdio(false);
    cin>>t;
    while(t--)
    {
        cin>>n>>k;
        if(!solve()) cout<<"-1 -1 -1\n";
    }
    return 0;
}

B题
求分子式的质量
解:栈的基础应用

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const int maxn = 1e5 + 10;
string a;
ll n,ans,k;
stack<ll>s;

void check()
{
    if(k)
    {
        k *= s.top();
        s.pop(); s.push(k);
        k = 0;
    }
}

int main()
{
    std::ios::sync_with_stdio(false);
    cin>>a; n = a.size();
    k = 0;
    for(int i = 0;i < n; ++i)
    {
        if(a[i] == '(') check(),s.push(-1);
        else if(a[i] == ')')
        {
            check();
            int sum = 0;
            while(!s.empty() && s.top() != -1)
            {
                sum += s.top();
                s.pop();
            }
            if(!s.empty() && s.top() == -1) s.pop();
            if(sum) s.push(sum);
        }
        else if(a[i] >= '0' && a[i] <= '9') k = k * 10 + a[i] - '0';
        else if(a[i] == 'C') check(),s.push(13LL);
        else if(a[i] == 'H') check(),s.push(1LL);
        else if(a[i] == 'O') check(),s.push(17LL);
    }
    check();
    while(!s.empty()) ans += s.top(),s.pop();
    cout<<ans<<'\n';
    return 0;
}

C题 简单模拟
F题 最后先手必胜
G题
选择(n/2)(向下取整)个才能拿走,并且不能选择在数组中相邻的数,一定要选第x个数,问选出的数的最大的和
解:很显然是DP,必须要选第x个,可以给第x个加上一个很大的数,最后减掉即可。
由于奇数时向下取整会损失精度,所以要分奇偶讨论
奇数:

第i个数字选或者不选
dp[i] = max{dp[i- 1],dp[i - 2] + a[i]}

偶数:

第i个数字选或者不选
dp[i] = max{sum[i- 1],dp[i - 2] + a[i]}   //如果用dp[i - 1]会少选一个,sum[i - 1]是唯一选法

代码

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const ll p = 1e16;   ///一定要足够大
const int maxn = 2e5 + 10;
ll n,x,a[maxn],dp[maxn],sum[maxn];

int main()
{
    std::ios::sync_with_stdio(false);
    cin>>n>>x;
    for(int i = 1;i <= n; ++i)
        cin>>a[i];
    a[x] += p;
    sum[1] = a[1];
    for(int i = 3;i <= n; i += 2)
        sum[i] = sum[i - 2] + a[i];
    for(int i = 2;i <= n; ++i)
    {
        if(i % 2) dp[i] = max(dp[i - 1],dp[i - 2] + a[i]);
        else      dp[i] = max(sum[i - 1],dp[i - 2] + a[i]);
    }
    cout<<(dp[n] - p)<<'\n';
    return 0;
}

I题
构造一个n×m的矩阵,使矩阵中任意相邻的两个数高度差都恰好为1,给出k条信息,说明(xi,yi)这个点的高度为hi。
解:从高度最小的点开始向四个方向bfs即可

#include<bits/stdc++.h>
using namespace std;

const int maxn = 1e5 + 10;
const int ma = 1e9 + 1;
int n,m,k;
vector<int>a[maxn];    ///数组开不下
vector<bool>vis[maxn];
int x,y,h;
int d[4][2] = {{-1,0},{0,-1},{0,1},{1,0}};

struct node
{
    int x,y;
    int h;
    node(int _x,int _y,int _h):x(_x),y(_y),h(_h){}
    bool operator<(const node& a) const   //注意区分
    {
        return h > a.h;
    }
};
priority_queue<node>q;  

bool solve()
{
    if(k)
    {
        while(k--)
        {
            cin>>x>>y>>h;
            if(a[x][y] != -ma && a[x][y] != h)
                return 0;
            a[x][y] = h;
            vis[x][y] = 1;
            q.push(node(x,y,h));
        }
    }
    else   //k = 0时
    {
        a[1][1] = 0;
        q.push(node(1,1,0)),vis[1][1] = 1;
    }
   // cout<<q.size()<<endl;
    while(!q.empty())
    {
        node r = q.top();
        q.pop();
        for(int i = 0;i < 4; ++i)
        {
            int xx = r.x + d[i][0];
            int yy = r.y + d[i][1];
            if(xx > n || xx < 1 || yy > m || yy < 1 || vis[xx][yy]) continue;
            if(a[xx][yy] != -ma && a[xx][yy] != r.h + 1) return 0;
            a[xx][yy] = r.h + 1;
            q.push(node(xx,yy,r.h + 1));
            vis[xx][yy] = 1;
        }
    }
    for(int i = 1;i <= n; ++i)
        for(int j = 1;j <= m; ++j)
            for(int kk = 0;kk < 4; ++kk)
            {
                int xx = i + d[kk][0];
                int yy = j + d[kk][1];
                if(xx > n || xx < 1 || yy > m || yy < 1) continue;
                if(abs(a[i][j] - a[xx][yy]) != 1) return 0;
            }
    return 1;
}

int main()
{
    std::ios::sync_with_stdio(false);
    cin>>n>>m>>k;
    for(int i = 1;i <= n + 1; ++i)
        for(int j = 1;j <= m + 1; ++j)
            a[i].push_back(-ma),vis[i].push_back(0);
    if(solve())
    {
        cout<<"Yes\n";
        for(int i = 1;i <= n; ++i)
            for(int j = 1;j <= m; ++j)
                cout<<a[i][j]<<((j == m)?'\n':' ');
    }
        else cout<<"No\n";
    return 0;
}