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

C Optimal Strategy 详解 【组合数学】【2021-ACM-ICPC-济南站】

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

C Optimal Strategy 详解 【组合数学】【2021-ACM-ICPC-济南站】

刚打完的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 
#include 
#include 
#include 
#include 
#include 
#include 

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>x;
		c[x]++;
		if(maxx < x){ //输入最大数 
			maxx = x;
		}
	//	cout< 

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

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

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