刚打完的icpc济南站的C题 Optimal Strategy 比赛时没A出来,思路在比赛时是想对了.但还在想是个dp题,推式子题还是模拟题哈哈.好菜啊.
一般这种大数取模的就得推式子,找规律啥的.今天补了c题,题面如下
(一)题目大意
输入n,再输入n个数.E和M轮流取一个数使各自取到的数字总和最大,E和M都足够聪明.问取数的过程有几种.
(二)思路分析
要让和最大,自然想到每个数都不能太小.若直接贪心每次双方都取最大第一个样例都解释不通.
再模拟样例二发现暗示比较明显,每个数都出现偶数次,样例三便是奇偶出现次数都有.
开一个桶数组c存每个数字的出现次数,则第 i 个数出现 c[i] 次
对于出现奇数次的数,先手取走最大的一个数,后手取走次大的出现的奇数次的数(若上一步先手将最大数取完则后手取走当前最大的出现奇数次的数) 进行完上述操作则提取出各个不相同的数,而这些数对于最后结果无影响.剩下的出现奇数次的数转为出现偶数次
对于出现偶数次的数,双方轮流从大到小拿,一方拿走一个另一方会立刻拿走相同的数.取当前数时有c[i]/2种方案.
从小到大考察每一个数的出现次数,当前数的可选方案数为c[i]/2.比当前数小的数的出现次数和sum可直接作为总和选取.
大数一定可在小数之前选取,故每个数的方案为C(c[i]/2+sum,c[i]/2).
每个数内部排列方案数为 c[i]!
最终结果如下
本题相比推理,更侧重过程的理解和模拟,结合实际去考虑
(三)AC代码
求阶乘可参见下面f[]数组的方法,我直接写的jiecheng函数超时了
处理组合数时如下直接求
**#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <cmath>
#include <math.h>
#include <string>
#include <cstring>
using namespace std;
typedef long long ll;
const int N = 1e6+10;
const int mod = 998244353;
ll c[N],a[N];
int maxx;
ll sum = 0;
ll f[N], unf[N];
//ll jiecheng(ll a){
// ll ans = 1;
// for(int i=1;i<=a;i++){
// ans = ans * i % mod; //别忘取模%mod,否则
// }
// return ans;
//}
ll zuhe(ll a,ll b){
return (ll)f[a] * unf[b] % mod * unf[a - b] % mod;
}
int main(){
//下面为求阶乘预处理的方法,速度快,否则jiecheng函数超时
unf[0] = unf[1] = f[0] = 1;
for (int i = 1; i < N; i ++) f[i] = (ll) f[i - 1] * i % mod;
for (int i = 2; i < N; i ++) unf[i] = (ll)(mod - mod / i) * unf[mod % i] % mod;
for (int i = 1; i < N; i ++) unf[i] = (ll) unf[i - 1] * unf[i] % mod;
ll res = 1;
int n;
cin>>n;
for(int i=0;i<n;i++){
int x;
cin>>x;
c[x]++;
if(maxx < x){ //输入最大数
maxx = x;
}
// cout<<maxx<<endl;
}
// cout<<endl;
// for(int i=1;i<=maxx;i++){
// cout<<i<<" "<<c[i]<<" *** ";
// }
// cout<<endl;
ll shang,xia;
for(int i=1;i<=maxx;i++){
if( c[i] != 0){
// cout<<c[i]<<endl;
shang = floor(c[i]/2);
xia = shang + sum;
// cout<<shang<<endl<<xia<<endl;
// cout<<jiecheng(c[i])<<endl;
// cout<<zuhe(xia,shang)<<endl;
// cout<<endl;
res = res * f[c[i]]%mod * zuhe(xia,shang)%mod;
sum += c[i];
}
}
// cout<<endl;
cout<<res<<endl;
return 0;
}
/*
3
1 2 2
6
1 3 2 2 3 1
12
1 1 4 5 1 4 1 9 1 9 8 10
*/
**