首页 > 其他分享 >AtCoder Beginner Contest 288 Ex A Nameless Counting Problem

AtCoder Beginner Contest 288 Ex A Nameless Counting Problem

时间:2023-10-03 18:22:16浏览次数:38  
标签:AtCoder typedef Beginner Contest text ll 个数 maxn mod

洛谷传送门

AtCoder 传送门

考虑到规定单调不降比较难搞。先设 \(g_t\) 为长度为 \(t\) 的满足条件的序列个数(可重且有顺序)。求这个可以设个 dp,\(f_{d, i}\) 表示考虑到从高到低第 \(d\) 位,当前 \(t\) 个数中有 \(i\) 个仍然顶上界,并且之前的位都满足异或分别等于 \(X\) 的限制。转移枚举从这一位开始不顶上界的数的个数即可。

现在考虑去重。设 \(f_t\) 为长度为 \(t\) 的满足条件的序列个数(不可重且无顺序)。注意到 \(x \oplus x = 0\),所以考虑枚举出现奇数次的数的总出现次数 \(i\),出现奇数次的数的种类数 \(j\),出现偶数次的数的种类数 \(k\)。设 \(\text{odd}(i, j)\) 为 \(i\) 个可区分的元素划分到 \(j\) 个不可区分的集合中,且每个集合的大小都是奇数的方案数,对称地设一个 \(\text{even}(i, j)\) 为 \(i\) 个可区分的元素划分到 \(j\) 个不可区分的集合中,且每个集合的大小都是偶数的方案数。那么我们有:

\[f_t = \sum\limits_{i = 0}^t \sum\limits_{j = 0}^i \binom{t}{i} \text{odd}(i, j) \sum\limits_{k = 0}^{t - i} \text{even}(t - i, k) (m + 1 - j)^{\underline k} g_j \]

从小到大算 \(f_t\) 即可。容易提前计算 \(h_{i, j} = \sum\limits_{k = 0}^i \text{even}(i, k) (m + 1 - j)^{\underline k}\) 做到 \(O(n^3)\) 计算。

现在我们知道了 \(f_t\) 了。因为 \(f_t\) 是有顺序的,所以计算答案时要先除一个 \(t!\) 转成无序。因为 \(f_t\) 不可重,所以我们枚举添加了 \(2i\) 个数,从 \(m\) 个数中可重地选出 \(2i\) 个数的方案数通过插板法可以算出是 \(\binom{m + i}{i}\),然后有:

\[\sum\limits_{i = 0}^{\left\lfloor\frac{n}{2}\right\rfloor} \frac{f_{n - 2i}}{(n - 2i)!} \binom{m + i}{i} \]

时间复杂度 \(O(n^3 \log V)\),瓶颈在一开始的 dp。

code
// Problem: Ex - A Nameless Counting Problem
// Contest: AtCoder - Toyota Programming Contest 2023 Spring Qual A(AtCoder Beginner Contest 288)
// URL: https://atcoder.jp/contests/abc288/tasks/abc288_h
// Memory Limit: 1024 MB
// Time Limit: 3000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
#define pb emplace_back
#define fst first
#define scd second
#define mkp make_pair
#define mems(a, x) memset((a), (x), sizeof(a))

using namespace std;
typedef long long ll;
typedef double db;
typedef unsigned long long ull;
typedef long double ldb;
typedef pair<ll, ll> pii;

const int maxn = 210;
const ll mod = 998244353;

inline ll qpow(ll b, ll p) {
	ll res = 1;
	while (p) {
		if (p & 1) {
			res = res * b % mod;
		}
		b = b * b % mod;
		p >>= 1;
	}
	return res;
}

ll n, m, K, fac[maxn], ifac[maxn], f[maxn], g[maxn][maxn], h[maxn][maxn], p[maxn][maxn], pw2[maxn];

inline ll C(ll n, ll m) {
	if (n < m || n < 0 || m < 0) {
		return 0;
	} else {
		return fac[n] * ifac[m] % mod * ifac[n - m] % mod;
	}
}

inline void upd(ll &x, ll y) {
	((x += y) >= mod) && (x -= mod);
}

void solve() {
	scanf("%lld%lld%lld", &n, &m, &K);
	pw2[0] = 1;
	for (int i = 1; i <= n; ++i) {
		pw2[i] = pw2[i - 1] * 2 % mod;
	}
	fac[0] = 1;
	for (int i = 1; i <= n; ++i) {
		fac[i] = fac[i - 1] * i % mod;
	}
	ifac[n] = qpow(fac[n], mod - 2);
	for (int i = n - 1; ~i; --i) {
		ifac[i] = ifac[i + 1] * (i + 1) % mod;
	}
	for (int t = 1; t <= n; ++t) {
		mems(g, 0);
		g[30][t] = 1;
		for (int d = 29; ~d; --d) {
			if (m & (1LL << d)) {
				for (int i = 0; i <= t; ++i) {
					for (int j = 0; j <= i; ++j) {
						int k = j & 1;
						k ^= ((K >> d) & 1);
						if (k && i == t) {
							continue;
						}
						upd(g[d][j], g[d + 1][i] * pw2[max(0, t - i - 1)] % mod * C(i, j) % mod);
					}
				}
			} else {
				for (int i = 0; i <= t; ++i) {
					if (i == t && (K & (1LL << d))) {
						continue;
					}
					g[d][i] = g[d + 1][i] * pw2[max(0, t - i - 1)] % mod;
				}
			}
		}
		for (int i = 0; i <= t; ++i) {
			upd(f[t], g[0][i]);
		}
	}
	mems(g, 0);
	g[0][0] = h[0][0] = 1;
	for (int i = 1; i <= n; ++i) {
		for (int j = 1; j <= n; ++j) {
			for (int k = 1; k <= i; ++k) {
				if (k & 1) {
					upd(g[i][j], g[i - k][j - 1] * C(i - 1, k - 1) % mod);
				} else {
					upd(h[i][j], h[i - k][j - 1] * C(i - 1, k - 1) % mod);
				}
			}
		}
	}
	for (int i = 0; i <= n; ++i) {
		for (int j = 0; j <= n; ++j) {
			ll mul = 1;
			for (int k = 0; k <= i; ++k) {
				upd(p[i][j], h[i][k] * mul % mod);
				if (m + 1 - j - k <= 0) {
					break;
				}
				mul = mul * (m + 1 - j - k) % mod;
			}
		}
	}
	f[0] = (K == 0);
	for (int i = 1; i <= n; ++i) {
		for (int j = 0; j <= i; ++j) {
			for (int k = 0; k <= j; ++k) {
				if (k < i) {
					upd(f[i], mod - C(i, j) * g[j][k] % mod * p[i - j][k] % mod * f[k] % mod);
				} else {
					ll coef = C(i, j) * g[j][k] % mod * p[i - j][k] % mod;
					f[i] = f[i] * qpow(coef, mod - 2) % mod;
				}
			}
		}
	}
	ll ans = 0;
	for (int i = 0; i * 2 <= n; ++i) {
		ll c = ifac[i];
		for (int j = m + i; j > m; --j) {
			c = c * j % mod;
		}
		upd(ans, f[n - i * 2] * ifac[n - i * 2] % mod * c % mod);
	}
	printf("%lld\n", ans);
}

int main() {
	int T = 1;
	// scanf("%d", &T);
	while (T--) {
		solve();
	}
	return 0;
}

标签:AtCoder,typedef,Beginner,Contest,text,ll,个数,maxn,mod
From: https://www.cnblogs.com/zltzlt-blog/p/17741445.html

相关文章

  • Atcoder abl c
    传送门题目描述有n个城市,m条双向路的图,问你最少添加几条路使得任意两个城市可以两两到达?样例样例输入3112样例输出:1题目解析这是个双向路的图,我们可以把它当成一个非连通图。在各个点之间有连线,要求我们算出如何能将整个图的各个部分连接起来。那么,我们只要算出这个......
  • AtCoder——第一题
    AtCoderBeginnerContest322FVacationQuery题目大意处理01字符串,给定Q次询问,询问区间内最长连续1的字符个数题目理解使用线段树维护区间需要使用懒标记下传修改信号线段树要维护7个信息(区间的最长连续1的个数、区间左端点开始连续1的个数、区间左端点开始连续0的个数......
  • AtCoder Grand Contest 056 D Subset Sum Game
    洛谷传送门AtCoder传送门考虑若\(n\)是奇数怎么做。枚举Alice第一次选的数\(a_i\),然后考虑把剩下的数两两结成一个匹配,若Bob选了其中一个,Alice就选另一个。容易发现排序后奇数位和它右边的偶数位匹配最优。那么设奇数位的和为\(A\),偶数位的和为\(B\),此时Alice获胜......
  • AtCoder Beginner Contest 178 E
    AtCoderBeginnerContest178EE-DistMax曼哈顿距离最大点对\(ans=max(|x_i-x_j|+|y_i-y_j|)\)考虑去绝对值,4种情况。sort一下取max即可。#include<bits/stdc++.h>usingnamespacestd;typedeflonglongll;constintN=2e5+10;intx[N],y[N];intp[4][N];......
  • 2022 China Collegiate Programming Contest (CCPC) Weihai Site
    PrefaceVP到自己学校出的题了可海星,不得不说学长们出的题比起昨天VP的CCPC2022广州做起来要舒服地多这场前面写题都很顺基本都是一发过,中期的medium也没怎么卡思路和卡机子,一道一道地慢慢出最后一个小时徐神RushF可惜没Rush出来,然后我和祁神坐在下面把B的做法给搞出来了,但不知......
  • The 2022 ICPC Asia Shenyang Regional Contest
    C.ClampedSequence因为\(n\)的范围不大,并且可以猜到\(l,r\)中应该至少有一个在\(a_i,a_i-1,a_i+1\)上。所以直接暴力枚举\(l\)或\(r\)然后暴力的计算一下#include<bits/stdc++.h>usingnamespacestd;#defineintlonglongusingvi=vector<int>;int32_tmain(){......
  • AtCoder Beginner Contest 322
    A-FirstABC2解题思路签到Code#include<bits/stdc++.h>usingnamespacestd;typedeflonglongLL;voidsolve(){ intn; cin>>n; strings; cin>>s; intp=s.find("ABC"); if(p==-1)cout<<p<<'\n&......
  • 2022 China Collegiate Programming Contest (CCPC) Guangzhou Onsite
    Preface好难啊这场广州站,不愧是5题金4题铜的超恶劣站,中档题普遍难度较高但我感觉主要原因还是题目出的太偏向于DP了,AI是本质差不多的树上换根DP,M又是个数位DP,导致像我这种不擅长DP的人直接中期坐牢但好在祁神大力切出了medium~hard的K题,然后最后一小时我把一直在想的A题丢给徐......
  • The 2022 ICPC Asia Xi'an Regional Contest
    C.CloneRanran最优解一定是先复制,在做题。最多只需要复制大约30次,直接枚举即可#include<bits/stdc++.h>usingnamespacestd;#defineintlonglonginta,b,c;voidsolve(){cin>>a>>b>>c;intres=LLONG_MAX;for(inti=0,t=1;i......
  • 2022 China Collegiate Programming Contest (CCPC) Mianyang Onsite
    Preface久违地VP一场,由于CCPC桂林在即因此最近就自主VP一下去年的CCPC这场打的时候全队不在状态,签完到后我就因为A题一个cornercase没考虑到卡了快两个小时然后好不容易搞过去徐神上来有狂WAE题,最后也是喜提+11后面写的D题也是需要特判,好家伙又是快到比赛结束才看出来最后......