• 2022牛客暑期多校训练营10(FHI)


    个人题解,非广告
    题集链接

    F Shannon Switching Game?

    博弈论

    思路

    从结束点开始向外考虑,结束点我们认为是必胜点,考虑其他点如何成为必胜点:

    如果某点存在两条(可重)边连接至另一个必胜点,则认为该点也是必胜点;

    以终点开始进行bfs寻找必胜点即可;

    代码
    #include 
    
    using namespace std;
    
    int win[110];
    int vis[110];
    vector<int> E[110];
    
    void bfs(int x)
    {
        queue<int> que;
        que.push(x);
        win[x] = 1;
        while (!que.empty())
        {
            int y = que.front();
            que.pop();
    
            for (int ty : E[y])
            {
                if (win[ty])
                    continue;
                vis[ty]++;
                if (vis[ty] == 2)
                {
                    win[ty] = 1;
                    que.push(ty);
                }
            }
        }
    }
    
    int main()
    {
        cin.tie(0)->sync_with_stdio(false);
        int s, t;
        int T;
        cin >> T;
        while (T--)
        {
            int n, m;
            cin >> n >> m >> s >> t;
            for (int i = 1; i <= n; i++)
            {
                vis[i] = 0;
                win[i] = 0;
                E[i].clear();
            }
            for (int i = 0; i < m; i++)
            {
                int u, v;
                cin >> u >> v;
                E[u].push_back(v);
                E[v].push_back(u);
            }
            bfs(t);
            if (win[s])
                cout << "Join Player\n";
            else
                cout << "Cut Player\n";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62

    H Wheel of Fortune

    概率期望

    思路

    假设 a,b 分别为 A,B 的最大受击数, t a t_a ta 表示 a 胜利的期望量(方案数*方案对应概率),则有
    t a = ∑ i = 1 a − 1 C i + b − 1 i ( 1 2 ) i + b t_a=\sum_{i=1}^{a-1}C_{i+b-1}^i(\frac 12)^{i+b} ta=i=1a1Ci+b1i(21)i+b

    代码

    队友代码如下

    #include 
    
    using namespace std;
    
    const int MOD = 998244353;
    
    long long Q_power(long long a, long long b = MOD - 2)
    {
        long long res = 1;
        while (b)
        {
            if (b & 1)
                res = res * a % MOD;
            a = a * a % MOD;
            b >>= 1;
        }
        return res;
    }
    
    const int N = 2e6 + 10;
    
    long long Fact[N];
    long long InvF[N];
    long long tw[N];
    
    void init()
    {
        Fact[0] = 1;
        for (int i = 1; i < N; i++)
        {
            Fact[i] = Fact[i - 1] * i % MOD;
        }
    
        InvF[N - 1] = Q_power(Fact[N - 1]);
    
        for (int i = N - 2; i >= 0; i--)
        {
            InvF[i] = InvF[i + 1] * (i + 1) % MOD;
        }
    
        tw[N - 1] = Q_power(Q_power(2 , N - 1));
        for (int i = N - 2 ; i >= 0 ; i -- ) {
            tw[i] = tw[i + 1] * 2;
            if(tw[i] >= MOD) tw[i] -= MOD;
        }
    }
    
    long long C(int n, int m)
    {
        if (n < m)
            return 0;
        return Fact[n] * InvF[m] % MOD * InvF[n - m] % MOD;
    }
    
    int main()
    {
        init();
        int a, b;
        cin >> a;
        a = (a - 1) / 10 + 1;
        for (int i = 0; i < 7; i++)
            cin >> b;
        cin >> b;
        b = (b - 1) / 10 + 1;
    
        long long A, B;
        A = B = 0;
        for (int i = 0; i < a; i++)
        {
            A += C(i + b - 1, i) * tw[i+b] % MOD;
            if (A >= MOD)
                A -= MOD;
        }
    //     for (int i = 0; i < b; i++)
    //     {
    //         B += C(i + a - 1, i) * tw[i+a] % MOD;
    //         if (B >= MOD)
    //             B -= MOD;
    //     }
    
        cout << A << endl;
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84

    I Yet Another FFT Problem?

    思路

    去掉绝对值后移项可得 a i + b l = a j + b k a_i+b_l=a_j+b_k ai+bl=aj+bk ,考虑两数之和不会超过 2e7 ,我们只需要去重后双重循环枚举两个数组的数字,记录每个和数的一组解,如果遇到当前和数已经有解,则发现答案;

    存在一种特殊情况,唯一解即为 a i = a j , b k = b l a_i=a_j,b_k=b_l ai=aj,bk=bl ,在去重时会被舍弃掉,特判这种情况即可;

    代码
    #include 
    
    using namespace std;
    const int maxn = 1e7 + 7;
    int n, m;
    vector<int> a(maxn), b(maxn);
    vector<int> mka(maxn, -1), mkb(maxn, -1);
    vector<int> pa, pb;
    vector<array<int, 2>> su(2 * maxn, {-1, -1});
    pair<pair<int, int>, pair<int, int>> ans = {{-1, -1}, {-1, -1}};
    int main()
    {
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= n; i++)
        {
            scanf("%d", &a[i]);
            if (mka[a[i]] == -1)
            {
                mka[a[i]] = i;
                pa.push_back(i);
            }
            else
            {
                ans.first.first = mka[a[i]];
                ans.first.second = i;
            }
        }
        for (int i = 1; i <= m; i++)
        {
            scanf("%d", &b[i]);
            if (mkb[b[i]] == -1)
            {
                mkb[b[i]] = i;
                pb.push_back(i);
            }
            else
            {
                ans.second.first = mkb[b[i]];
                ans.second.second = i;
            }
        }
        if (ans.first.first != -1 && ans.second.first != -1)
        {
            printf("%d %d %d %d", ans.first.first, ans.first.second, ans.second.first,
                   ans.second.second);
            return 0;
        }
        for (int i : pa)
        {
            for (int j : pb)
            {
                if (su[a[i] + b[j]][0] == -1)
                {
                    su[a[i] + b[j]] = {i, j};
                }
                else
                {
                    printf("%d %d %d %d", su[a[i] + b[j]][0], i, j, su[a[i] + b[j]][1]);
                    return 0;
                }
            }
        }
        cout << "-1\n";
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
  • 相关阅读:
    DolphinScheduler
    ucore实验二
    Java岗秋招最全面试攻略,看这份Java架构面试核心手册,足够了
    前后端分离项目知识汇总(阿里云Oss,EasyExcel,视频点播,SpringCloud,Redis,Nuxt)
    前端基于excljs导出xlsx时图片资源的处理及踩坑实录
    数据仓库与数据挖掘的第一章课后习题
    Mac系统下 脚本sed的简单使用
    基于gensim实现word2vec模型(附案例实战)
    SpringBoot集成自然语言处理hanlp工具包
    水库大坝可视化智能远程监管方案,助力安全监测智能巡检
  • 原文地址:https://blog.csdn.net/Tan_Yuu/article/details/126454580