栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

2021 ICPC Jinan C Optimal Strategy

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

2021 ICPC Jinan C Optimal Strategy

题意:

题意很明确,n个值,两个人轮流取,问有多少种可能,然后取模。
这个题意看看样例应该很好理解

分析

首先统计一下每个数的个数,然后顺序排好,就没有问题了。
我推出的第一条性质是如果存在一个奇数个的大数,那么它一定会比这个数下面的数先被取走,偶数个数的大数,乃至偶数个的任何数都没有这个性质。
由此再考虑偶数个的数字,我们发现偶数取的规律十分随意,但是呢,有一个很抽象的性质,对于后手来说,先手如果取了一个偶数个数的数,那么我作为后手一定会去选择一个比你大或者等于你的偶数的数,这里的前提是没有个数的数了,因为前面说了,奇数一定在此之前就被取走了;(感性理解的话,这些数都是成对的,你拿啥我拿啥,甚至我拿的比你还大,那么两个人都用此策略,是完全不会影响答案的)理解之后发现规律,把对相同的偶数看作括号,则上面和下面的不能相交,也就是如果有3 ,3 ,4 ,4 四个数字,我如果拿3,你拿4我肯定不能拿3 了,这样就是相交,3,4,4,3就是包含,就是不相交的情况。其次呢,对于成对的大数,要么与小数并列,要么被小数的括号包含起来。
考虑这样的状态数,从小到大遍历,把成对的大数一起放,下面的小数是可以放进小数中间的,也就是放4,4 的时候,可以放成3,3,4,4或者4,4,3,3或者3,4 ,4,3;但是大的是在一起的,小数是可以分开的。
所以这样的话,我们考虑每个数往里放的贡献,累乘起来就好了。
这里挂出来官方题解:

首先ci!是肯定大家都知道的,然后每次后面的组合公式的意思是,对于每次往里放大数的时候,成对的放,就有ci/2取整对,然后考虑到放完之后会有
种状态,那么从中选出ci/2种作为放入的序列,然后再乘上阶乘就是每次的答案,累乘起来就是结果。

#include 
#define ll long long
const ll mod = 998244353;
const ll p = 998244353;
const ll N = 2e6 + 1000;
using namespace std;
ll arr[N];
ll ux[N];
vector st;
typedef long long LL;
LL n, m;
LL quick_mod(LL a, LL b) {
    LL ans = 1;
    a %= p;
    while (b) {
        if (b & 1) {
            ans = ans * a % p;
            b--;
        }
        b >>= 1;
        a = a * a % p;
    }
    return ans;
}
LL C(LL n, LL m) {
    if (m > n) return 0;
    LL ans = 1;
    for (int i = 1; i <= m; i++) {
        LL a = (n + i - m) % p;
        LL b = i % p;
        ans = ans * (a * quick_mod(b, p - 2) % p) % p;
    }
    return ans;
}
LL Lucas(LL n, LL m) {
    if (m == 0) return 1;
    return C(n % p, m % p) * Lucas(n / p, m / p) % p;
}
inline void solve() {
    ux[0] = 1;
    for (ll i = 1; i <= 1000009; i++) {
        ux[i] = ux[i - 1] * i;
        ux[i] %= mod;
    }
    ll n;
    scanf("%lld", &n);
    for (ll i = 0; i < n; i++) {
        scanf("%lld", &arr[i]);
    }
    sort(arr, arr + n);
    ll cnt = 1;
    for (ll i = 1; i < n; i++) {
        if (arr[i] == arr[i - 1])
            cnt++;
        else
            st.push_back(cnt), cnt = 1;
    }
    st.push_back(cnt);
    ll t = 0, ans = 1;
    for (ll i = 0; i < st.size(); i++) {
        int uu=st[i]/2;
        ans*=Lucas(uu+t,uu);
        ans%=mod;
        ans*=ux[st[i]];ans%=mod;
        t+=st[i];
    }
    printf("%lldn", ans % mod);
}
int main() {
    solve();
    return 0;
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/528986.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号