首页 > 其他分享 > ARC134F Flipping Coins

ARC134F Flipping Coins

时间:2023-07-23 22:03:37浏览次数:38  
标签:ch int lim Coins ARC134F Flipping cdots mathtt EGF

pb 讲课没讲的题,感觉很牛逼啊!但不是牛逼在多项式,因为多项式大家应该都会。

考虑从前往后扫的过程,只要有正面就翻成反面,所以最后只有可能是当 \(p_i<i\) 且 \(i\) 没有被翻面时才对 \(k\) 有贡献。那么考虑一条链 \(1\to 2\to \cdots \to m\),并且 \(\forall 1\le i< m,p_i=i+1\),那么此时翻了 \(1\) 就会翻 \(2\),翻了 \(3\) 就会翻 \(4\)……不难发现此时当且仅当 \(2\nmid m\) 才对 \(k\) 有 \(1\) 的贡献。

于是考虑把排列分成若干置换环,并单独考虑每一个环。不难发现,我们在每个置换环的最小值处断环成链,最后这个环对 \(k\) 的贡献就是这条链上正面朝上的硬币个数,就是这条链长度为奇数的极长上升子段个数

把所有链按照最小值从大到小进行排序,然后排成一排变成排列 \(q\)。不难发现 \(p,q\) 是一一对应的,同时 \(p\) 对应的 \(k\) 就是 \(q\) 长度为奇数的极长上升子段个数。

接下来是一个很神仙的转化:把每个极长上升子段拆成 \(\mathtt{ABABAB\cdots C}\) 的形式,即分成若干长度为 \(2\) 和 \(1\) 的小段,长度为 \(2\) 的标为 \(\mathtt{AB}\),长度为 \(1\) 的标为 \(\mathtt{C}\),\(k\) 就是长为 \(1\) 的小段即 \(\mathtt{C}\) 的个数。

发现我们所需要满足的条件如下:

  • 由于 \(\mathtt{ABABAB\cdots}\) 形如上升状子段,所以每个 \(\mathtt{A}\) 代表的数都比后面相邻的 \(\mathtt{B}\) 小。
  • \(\mathtt{B}\) 是没有限制的,因为它可以作为长度为偶数的极长上升子段末尾,也可以在后面接上一个单独的一个 \(\mathtt{C}\)。
  • 每个 \(\mathtt{C}\) 都要大于后面的数,不管是 \(\mathtt{A}\) 还是 \(\mathtt{C}\),否则可以匹配成 \(\mathtt{AB}\)。

所以我们以每个 \(\mathtt{B}\) 为末尾断开,把序列分成形如 \((\mathtt{CC\cdots CAB})(\mathtt{CC\cdots CAB})(\mathtt{CC\cdots C})\) 的形式。

然后考虑生成函数,列出整个排列的 EGF \(F(x)\),形如 \(\mathtt{CC\cdots CAB}\) 的 EGF \(G(x)=\sum\limits_{i=2}(i-1)w^{i-2}\dfrac{x_i}{i!}\),形如 \(\mathtt{CC\cdots C}\) 的 EGF \(H(x)=\sum\limits_{i=0}w^i\dfrac{x^i}{i!}\),然后显然有 \(F(x)=F(x)G(x)+H(x)\),即 \(F(x)=\frac{H(x)}{1-G(x)}\),求逆即可。

(为什么是 EGF 傻子都知道,不要再过来找我问了。)

当然直接推朴素的 dp 应该有一个可以分治 NTT 的形式,这个也能做,不过本质上其实就是 EGF 卷积。

然后找个板子过来就 \(O(n\log^2n)\) 或者 \(O(n\log n)\) 随便做了。

// Problem: F - Flipping Coins
// Contest: AtCoder - AtCoder Regular Contest 134
// URL: https://atcoder.jp/contests/arc134/tasks/arc134_f
// Memory Limit: 1024 MB
// Time Limit: 5000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
#define int long long
using namespace std;

namespace vbzIO {
	char ibuf[(1 << 20) + 1], *iS, *iT;
	#if ONLINE_JUDGE
	#define gh() (iS == iT ? iT = (iS = ibuf) + fread(ibuf, 1, (1 << 20) + 1, stdin), (iS == iT ? EOF : *iS++) : *iS++)
	#else
	#define gh() getchar()
	#endif
	#define mt make_tuple
	#define mp make_pair
	#define fi first
	#define se second
	#define pc putchar
	#define pb push_back
	#define ins insert
	#define era erase
	#define bg begin
	#define rbg rbegin
	typedef tuple<int, int, int> tu3;
	typedef pair<int, int> pi;
	inline int rd() {
		char ch = gh();
		int x = 0;
		bool t = 0;
		while (ch < '0' || ch > '9') t |= ch == '-', ch = gh();
		while (ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + (ch ^ 48), ch = gh();
		return t ? ~(x - 1) : x;
	}
	inline void wr(int x) {
		if (x < 0) {
			x = ~(x - 1);
			putchar('-');
		}
		if (x > 9)
			wr(x / 10);
		putchar(x % 10 + '0');
	}
}
using namespace vbzIO;

const int N = 3e6 + 300;
const int P = 998244353;
const int g = 114514;

int n, w, tr[N];
int f[N], h[N], fac[N], inv[N], ifac[N];

int qpow(int p, int q) {
    int res = 1;
    while (q) {
        if (q & 1) res = res * p % P;
        p = p * p % P, q >>= 1;
    }
    return res;
}

void init(int lim) {
	fac[0] = ifac[0] = inv[1] = 1;
	for (int i = 1; i <= lim; i++) {
		if (i > 1) inv[i] = inv[P % i] * (P - P / i) % P;
		fac[i] = fac[i - 1] * i % P, ifac[i] = ifac[i - 1] * inv[i] % P;
	}
}

const int gi = qpow(g, P - 2);

void NTT(int *f, int lim, int op){
    for (int i = 0; i < lim; i++) 
        if (i < tr[i]) swap(f[i], f[tr[i]]);
    for (int o = 2, k = 1; k < lim; o <<= 1, k <<= 1) {
    	int tg = qpow(~op ? g : gi, (P - 1) / o);
    	for (int i = 0; i < lim; i += o) {
    		for (int j = 0, w = 1; j < k; j++, (w *= tg) %= P) {
    			int x = f[i + j];
    			int y = w * f[i + j + k] % P;
    			f[i + j] = (x + y) % P;
    			f[i + j + k] = (x - y + P) % P;
			}
		}
	}
	if (op == 1) return;
	int iv = qpow(lim, P - 2);
	for (int i = 0; i < lim; i++) 
		(f[i] *= iv) %= P;
}

void INV(int *f, int *g, int n) {
	if (n == 1) return g[0] = qpow(f[0], P - 2), void();
	INV(f, g, (n + 1) >> 1);
	static int t[N];
	int lim = 1, len = 0;
	while (lim < (n << 1)) lim <<= 1, len++;
    for (int i = 0; i < lim; i++) 
		tr[i] = (tr[i >> 1] >> 1) | ((i & 1) << (len - 1));
	for (int i = 0; i < n; i++) t[i] = f[i];
	for (int i = n; i < lim; i++) t[i] = 0;
	NTT(t, lim, 1), NTT(g, lim, 1);
	for (int i = 0; i < lim; i++) 
		g[i] = (2 - g[i] * t[i] % P + P) % P * g[i] % P;
	NTT(g, lim, -1);
	for (int i = n; i < lim; i++) g[i] = 0;
}

int C(int n, int m) {
	if (n < m || m < 0) return 0;
	return fac[n] * ifac[m] % P * ifac[n - m] % P;
}

signed main() {
    n = rd(), w = rd(), init(n);
    f[0] = 1;
    for (int i = 2; i <= n; i++) 
    	f[i] = (P - 1) * ifac[i] % P * (i - 1) % P * qpow(w, i - 2) % P;
    INV(f, h, n + 1);
    for (int i = 0; i <= n; i++) 
    	(h[i] *= fac[i]) %= P;
    int res = 0;
    for (int i = 0; i <= n; i++) 
    	(res += C(n, i) * qpow(w, i) % P * h[n - i] % P) %= P;
    wr(res);
    return 0;
}

标签:ch,int,lim,Coins,ARC134F,Flipping,cdots,mathtt,EGF
From: https://www.cnblogs.com/Ender32k/p/17575963.html

相关文章

  • 【贪心】AGC018C Coins
    ProblemLink现在有\(X+Y+Z\)个人,第\(i\)个人有三个权值\(a_i,b_i,c_i\),现在要求依次选出\(X\)个人,\(Y\)个人和\(Z\)个人(一个人只能选依次),使得这\(X\)个人的\(a\)权值,\(Y\)个人的\(b\)权值,\(Z\)个人的\(c\)权值之和最大。\(X,Y,Z\le10^5\)。技巧:排序证明......
  • 【每日一题】Problem 327A - Flipping Game
    原题解决思路计算数字"1"的最大数目,可以转换成计算数组最大和,即求\(maxSum(oldArraySum-(1\rightarrow0)+(0\rightarrow1))\RightarrowoldArraySum+maxSum(flipSum)\)误区注意:题目要求必须执行一次,因此起始值不是0而是-1#include<bits/stdc++.h>intm......
  • UVA - 562 Dividing coins 经典01背包
    题目大意:给出一系列硬币,要求分给两个人,且两个人得到的硬币差达到最小值解题思路:用d[i]表示i这个数是否能被表示,则如果d[i-num[j]]==1的话,num[j]表示硬币的价值,则d[i]就可以被表示,最后只要判断sum>>1然后递减到0的期间遇到哪个数字能表示的,能表示的话就找到结果了,结果为sum-2*i,具体......
  • DP(分组背包两种二进制优化) Problem S:Coins(HDU 2844)
    ProblemSTimeLimit:2000/1000ms(Java/Other)   MemoryLimit:32768/32768K(Java/Other)TotalSubmission(s):12   AcceptedSubmission(s):0ProblemDesc......
  • 「解题报告」ARC134F Flipping Coins
    简单题。但是我不会。首先考虑这个过程:我们从前往后扫,只要有正面就给翻成反面,那么最后留下的正面只有可能是当\(p_i<i\)且\(i\)没有被翻面时才会造成\(1\)的贡献......
  • Square Coins(母函数)
    ProblemDescriptionPeopleinSilverlandusesquarecoins.Notonlytheyhavesquareshapesbutalsotheirvaluesaresquarenumbers.Coinswithvaluesofall......
  • 832. Flipping an Image
    ​​cppvector<vector<int>>flipAndInvertImage(vector<vector<int>>&A){for(inti=0;i<A.size();++i){for(intj=0;j<(A[i].size()/2);++j){in......
  • [ABC261D] Flipping and Bonus 题解
    [ABC261D]FlippingandBonusSolution目录[ABC261D]FlippingandBonusSolution更好的阅读体验戳此进入题面SolutionCodeUPD更好的阅读体验戳此进入题面掷$n$......
  • Educational DP Contest I - Coins(概率DP)
    https://atcoder.jp/contests/dp/tasks/dp_i题目大意:给定n个硬币,n是奇数,每个硬币朝上的概率是ai问我们一半以上的硬币处于正面的概率是多少?SampleInput130.30......
  • Codeforces875B-Sorting the Coins
    SortingtheCoinsRecently,DimametwithSashainaphilatelicstore,andsincethentheyarecollectingcoinstogether.Theirfavoriteoccupationistosortco......