首页 > 其他分享 >AtCoder Regular Contest 139 E Wazir

AtCoder Regular Contest 139 E Wazir

时间:2023-05-26 16:14:11浏览次数:47  
标签:AtCoder typedef int res ll long times Regular 139

洛谷传送门

AtCoder 传送门

好题。

这种题一般可以考虑,观察最优解的性质,对于性质计数。

发现如果 \(n,m\) 均为偶数,可以放满。就是类似这样:

#.#.#.
.#.#.#
#.#.#.
.#.#.#

因此答案就是 \(2\)。

如果 \(n,m\) 有一个为偶数,不妨假设 \(n\) 为偶数。那么最优解形似:

#.#..
.#..#
#..#.
..#.#

可以发现答案是 \(n \times \frac{m - 1}{2}\),并且一行有且仅有两个连续格子是 .,并且上下两行两个连续 . 的坐标一定相差 \(1\)。

那么对于 \(n,m\) 都是奇数的情况,答案是 \(\max(n \times \frac{m - 1}{2}, m \times \frac{n - 1}{2})\)。不妨假设 \(n \ge m\),那么答案是 \(n \times \frac{m - 1}{2}\),性质同上。

下面假设最优解是 \(n\) 行每行放 \(\frac{m - 1}{2}\) 个。

考虑将一个方阵映射到一个比较好计数的序列。设 \(a_i\) 为第 \(i\) 行,连续两个 . 的位置。那么实际上要满足:

\[\begin{cases} \forall i \in [1, n], a_i - a_{i + 1} \equiv \pm 1 \pmod{m} \\ a_1 = a_{n + 1} \end{cases} \]

考虑对于 \(b_i = a_i - a_{i + 1} = \pm 1\) 计数,这样要求 \(\sum\limits_{i=1}^n b_i = 0\)。

注意因为 \(n,m\) 可能被 swap 过,所以只能保证 \(\min(n, m) \le 10^5\)。

  • 当 \(n \le 10^5\),枚举有多少个 \(a_i - a_{i + 1} = 1\),多少个 \(= -1\),用组合数算;
  • 当 \(m \le 10^5\),考虑构造多项式 \(f(x) = (x + x^{-1})^n \pmod{x^m - 1}\),那么就是要求 \(f(x)\) 的常数项。感性理解,每次可以给指数 \(+1\) 或 \(-1\),最后要求指数 \(= 0\)。这个可以多项式快速幂算。

注意最后答案要 \(\times m\),因为 \(a_1\) 任意。

时间复杂度 \(O(\min(n, m) \log n \log m)\)。

code
// Problem: E - Wazir
// Contest: AtCoder - AtCoder Regular Contest 139
// URL: https://atcoder.jp/contests/arc139/tasks/arc139_e
// Memory Limit: 1024 MB
// Time Limit: 10000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

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

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

const int maxn = 1000100;
const int N = 1000000;
const ll mod = 998244353, G = 3;

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, fac[maxn], ifac[maxn], r[maxn];

void init() {
	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;
	}
}

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;
	}
}

typedef vector<ll> poly;

inline poly NTT(poly a, int op) {
	int n = (int)a.size();
	for (int i = 0; i < n; ++i) {
		if (i < r[i]) {
			swap(a[i], a[r[i]]);
		}
	}
	for (int k = 1; k < n; k <<= 1) {
		ll wn = qpow(op == 1 ? G : qpow(G, mod - 2), (mod - 1) / (k << 1));
		for (int i = 0; i < n; i += (k << 1)) {
			ll w = 1;
			for (int j = 0; j < k; ++j, w = w * wn % mod) {
				ll x = a[i + j], y = w * a[i + j + k] % mod;
				a[i + j] = (x + y) % mod;
				a[i + j + k] = (x - y + mod) % mod;
			}
		}
	}
	return a;
}

inline poly operator * (poly a, poly b) {
	a = NTT(a, 1);
	b = NTT(b, 1);
	int n = (int)a.size();
	for (int i = 0; i < n; ++i) {
		a[i] = a[i] * b[i] % mod;
	}
	a = NTT(a, -1);
	ll inv = qpow(n, mod - 2);
	for (int i = 0; i < n; ++i) {
		a[i] = a[i] * inv % mod;
	}
	return a;
}

inline poly qpow(poly a, ll p) {
	int n = (int)a.size();
	poly res(n);
	res[0] = 1;
	while (p) {
		if (p & 1) {
			res = res * a;
			for (int i = m; i <= m * 2; ++i) {
				res[i % m] = (res[i % m] + res[i]) % mod;
				res[i] = 0;
			}
		}
		a = a * a;
		for (int i = m; i <= m * 2; ++i) {
			a[i % m] = (a[i % m] + a[i]) % mod;
			a[i] = 0;
		}
		p >>= 1;
	}
	return res;
}

void solve() {
	scanf("%lld%lld", &n, &m);
	if (n % 2 == 0 && m % 2 == 0) {
		puts("2");
		return;
	}
	if (m % 2 == 0 || ((n & 1) && (m & 1) && n < m)) {
		swap(n, m);
	}
	ll ans = 0;
	if (n <= 100000) {
		for (int i = 0; i <= n; ++i) {
			if ((i - (n - i)) % m == 0) {
				ans = (ans + C(n, i)) % mod;
			}
		}
	} else {
		int k = 0;
		while ((1 << k) <= m * 2) {
			++k;
		}
		for (int i = 1; i < (1 << k); ++i) {
			r[i] = (r[i >> 1] >> 1) | ((i & 1) << (k - 1));
		}
		poly A(1 << k);
		A[1] = A[m - 1] = 1;
		poly res = qpow(A, n);
		ans = res[0];
	}
	printf("%lld\n", ans * (m % mod) % mod);
}

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

标签:AtCoder,typedef,int,res,ll,long,times,Regular,139
From: https://www.cnblogs.com/zltzlt-blog/p/17434992.html

相关文章

  • 【atcoder begin 302】【e题 Isolation 】JAVA的快速输入输出
    importjava.io.*;importjava.util.HashSet;importjava.util.Set;/***@authorfishcanfly*/publicclassMain{publicstaticvoidmain(String[]args)throwsIOException{//BufferedReaderbr=newBufferedReader(newInputStreamReader(......
  • AtCoder Beginner Contest 300(E,F)
    AtCoderBeginnerContest300(E,F)E(概率dp)E这个题意大致就是一开始有一个初始数\(x\)为\(1\),然后我们有一个骰子,最后得到的点数概率一样,为\(\frac{1}{6}\),如果这一次得到的点数为\(i\),那么\(x\)会变成\(i\timesx\),问最后得到数\(n\)的概率为多少先感性的分析一波,对于......
  • CF1139E Maximize Mex 题解
    Description\(n\)个学生,\(m\)个社团。每个学生有一个能力值,且仅属于一个社团。这\(d\)天内,每天从\(m\)个社团中选人,使得选出的人的能力值的\(\text{mex}\)最大。每天会有一个人在选人之前退团。\(d,m\leqn\leq5000\)Solution巧妙建图题。首先,我们可以很显然的......
  • AtCoder Regular Contest 146 D >=<
    洛谷传送门AtCoder传送门考虑直接增量构造。把条件拆成形如\(a_u\gex\)时\(a_v\gets\max(a_v,y)\),连边,跑类似一个spfa的东西,就行了。这样一定能构造出一组和最小的解。code//Problem:D->=<//Contest:AtCoder-AtCoderRegularContest146//URL:http......
  • AtCoder Beginner Contest 193 F Zebraness
    洛谷传送门AtCoder传送门复习一下最小割。考虑翻转横纵坐标和为奇数的颜色,那么就变成了,相邻两个格子,相同颜色产生\(1\)的贡献。一眼P4313文理分科。每个格子被分到\(S\)表示染黑,分到\(T\)表示染白。对于每两个相邻格子,建两个虚点,分别表示它们都染黑或者都染白的情况......
  • AtCoder Beginner Contest 302 H. Ball Collector 题解
    AtCoderBeginnerContest302H.BallCollector题意跳过。可以视作将\(a_i,b_i\)之间连了一条边,然后\(a_i,b_i\)之间只能选一个等价于对于一条边只能选择其一个端点。那么对于只包含树的联通块而言,如果都选择儿子节点,那么会有一个根节点无法被选择上;而对于包含至少一个......
  • AtCoder Beginner Contest 302(E,F,G)
    AtCoderBeginnerContest302(E,F,G)E(图,set)E这个题意大致为一开始给出\(n\)个点,没有一条边,后面陆续会有\(q\)次操作,以下两种方式\(1\),输入两个点,代表连接这两个点\(2\),输入一个点,意在把所有和这个点相连的边都删除每一次操作后我的都需要知道操作后还有多少个孤立无援的点(没......
  • AtCoder Regular Contest 132 E Paw
    洛谷传送门AtCoder传送门感觉挺educational的。观察最终形态,发现根据洞分段,有且只有一段没被覆盖,并且左端是向左的脚印,右端是向右的脚印。最终状态就这几种了,直接枚举,概率乘贡献即可。发现左端和右端不影响到对方是对称的,直接求出一边的概率。设\(f_i\)为\(i\)个洞,填......
  • AtCoder Regular Contest 132 F Takahashi The Strongest
    洛谷传送门AtCoder传送门没见过这种在新运算下做卷积的题,感觉挺新奇的。考虑Takahashi成为绝对赢家的必要条件,发现前提是Aoki和Snuke出的要相同。不妨将每种策略映射到一个四进制数(\(P\to1,R\to2,S\to3\)),定义运算\(x\otimesy=\begin{cases}x&x=y\\0......
  • AtCoder Beginner Contest 296
    AtCoderBeginnerContest296D题意给出n和m,问\(1\leqi,j\leqn\),使得\(ij\geqm\),求出这个乘积的最小值思路这两个乘数至少有一个在\([1,\sqrt{m}]\),枚举代码voidsolve(){ cin>>n>>m; intx=sqrt(m); if(n>=m){cout<<m<<endl;return;} if(x*x==m)......