题目链接:http://acm.hdu.edu.cn/downloads/CCPC2018-Hangzhou-ProblemSet.pdf
总结:
上来是俩水题,然后接着看B,C题其实都是思维水题。
B题不需要推公式,dfs可以直接卡过,C题手动模拟出结论?
不过暴露出来了我对博弈的有点遗忘和数学公式推理薄弱。确实好久没见过了,为了避免以后碰到凉凉,还是有必要认真重新复习下。
B.Master of Phi
比赛的时候写了一发dfs超时。但复杂度好像能过,重写了一下:(注意:预处理,以及dfs求所有组合)

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int mod = 998244353;
int p[25], q[25], m;
inline int q_pow(int a, int b){
    int ans = 1;
    while(b > 0){
        if(b & 1){
            ans = ans * a % mod;
        }
        a = a * a % mod;
        b >>= 1;
    }
    return ans;
}

int n, res, A[25];
inline void dfs(int u, int tmp)
{
    if(u == m + 1)
    {
        res = (res + tmp)%mod;
        return ;
    }
    dfs(u + 1, tmp * A[u] % mod);
    dfs(u + 1, tmp);
}

signed main()
{
    int t;
    cin >> t;
    while(t--)
    {
        res = 0;
        n = 1;
        cin >> m;
        for(int i = 1; i <= m; i++){
            cin >> p[i] >> q[i];
            A[i] = q[i] * (p[i] - 1) % mod * q_pow(p[i], mod-2) % mod;
            n = n * q_pow(p[i], q[i]) % mod;
        }

        dfs(1, 1);
        cout << res*n % mod << endl;
    }
}

但是这道题是一道利用积性函数性质和欧拉函数性质的好题
积性函数:https://baike.baidu.com/item/%E7%A7%AF%E6%80%A7%E5%87%BD%E6%95%B0/8354949?fr=aladdin
欧拉函数:https://baike.baidu.com/item/%E6%AC%A7%E6%8B%89%E5%87%BD%E6%95%B0
推公式即可。

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int mod = 998244353;
int p[25], q[25];
int q_pow(int a, int b){
    int ans = 1;
    while(b > 0){
        if(b & 1){
            ans = ans * a % mod;
        }
        a = a * a % mod;
        b >>= 1; 
    } 
    return ans;
}
signed main()
{
    int t; cin >> t;
    while(t--)
    {
        int m, ans = 1; 
        cin >> m;
        for(int i = 1; i <= m; i++) {
            cin >> p[i] >> q[i];
            int tmp = q_pow(p[i], q[i]) * ((1 + q[i] - (q[i] * q_pow(p[i], mod-2) % mod) + mod) % mod) % mod;
            ans = ans * tmp % mod;
        }
        cout << ans << endl;
    }
}

C(博弈).
n个堆的取石子游戏,要求每个回合Hakase取两次, Nano取1次。
思路:
1.Hakase先手,从特殊角度思考,如果全是1怎么办?手动模拟发现如果有n堆石子,n个1,若3|n则Hakase输掉游戏,其他情况Hakase必赢。除了刚刚说的那种情况,尝试不利于Hakase构造任何一种最终状态之前的状态,会发现Hakase总能获胜。
2,首先由1可知,如果3|n在Hakase先手的时候输掉游戏,那里要求n个包都是1,只需要让一个包变成不为1的数,Nano先手让这个包变成1即可。如果现在都是1,我们再次手动模拟发现如果n%3=1都是Nano赢,并且由于Nano先手,其实如果Nano第一次要取的那个包如果有多于1的石子也是可以的。

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int t;
    cin >> t;
    while(t--)
    {
        int n, d;
        cin >> n >> d;
        int cnt = 0;
        for(int i = 1, x; i <= n; i++) {
            cin >> x;
            if(x == 1) ++cnt;
        }
        if(d == 1)
        {
            if(cnt == n && n % 3 == 0)
            {
                cout << "No" << endl;
            }
            else cout << "Yes" << endl;
        }
        else
        {
            if(cnt == n && n % 3 == 1)
            {
                cout << "No" << endl;
            }
            else if(cnt == n-1 && n % 3 == 1)
            {
                cout << "No" << endl;
            }
            else if(cnt == n-1 && n % 3 == 0)
            {
                cout << "No" << endl;
            }
            else
            {
                cout << "Yes" << endl;
            }
        }
    }
}