CF838C(博弈+FWT子集卷积+多项式ln、exp)
传送门:
http://codeforces.com/problemset/problem/838/C
题解:
如果一个字符串的排列数是偶数,则先手必胜,因为如果下一层有后手必赢态,直接转移过去,不然,就一直耗着,因为是偶数,所以会让后手进入下一层,则后手必输。
排列数是偶数,打表发现\(|s|\)是奇数时,先手必赢,否则后手必赢,接下来尝试归纳这个结论。
|s|<=2时显然成立。
对于\(|S|\)奇数,排列个数是奇数时,设a[i]表示第i个字符出现次数,排列个数=\(\binom{|S|}{a[1],a[2],…,a[k]}\),我们需要使一个a[i]减一,然后新的排列个数还是奇数,因为\(|S|\)是奇数,所以一定可以找到一个是奇数的\(a[i]\),然后满足。
对于\(|S|\)偶数,排列个数是奇数时,不管新的的排列个数是奇数还是偶数,因为下一个长度是奇数,新状态都会先手比胜。
因此得证。
那么问题转换为选\(a[1],a[2],…,a[k],使{\forall i,j(i≠j)}满足a[i]~and~a[j]=0\)。
一个比较容易的思路,\(>0\)的\(a[i]\)肯定不超过\(log ~ n\)个,不难想到子集卷积,最后乘一个组合数。
子集卷积解决下面这个问题:
\(c[i|j]+=a[i]*b[j](i~and~j=0)\)
套路的解决方法是再记录一维表示1的个数,只要最后搞出的结果的1的个数相符就表示没有出现\(i~and~j≠0\)。
那么复杂度是\(O(n~log^3~n)\),卡卡常就能过。
事实上有\(O(n~log^2n)\)的做法。
考虑不枚举\(>0\)的个数,直接暴力卷积:
记\(f[i][j]\)表示1的个数为i时状态为j的的系数和。
这个东西可以快速幂卷对吧,不过还是\(log^3\)的。
把状态反过来\(f[j][i]\)表示状态为j的,1的个数为i的系数和,注意这个j已经FWT过了。
那么后面就相当于普通的多项式快速幂,求个ln*k再exp即可。
注意到项数很少,可以暴力ln和exp。
暴力exp可以用组合意义搞:
有\(F\),设\(f(x)\)为它的EGF,即\(f(x)[x^n]=F[n]/n!\)
那么有\(g(x)=e^{f(x)}\)意义可以为有标号连通图->有标号一般图,\(g(x)\)是\(G=e^{f(x)}\)的EGF,所以有dp:
\(G[n]*n!=\sum_{i=1}^{n}\binom{n-1}{i-1}*F[i]*i!*G[n-i]*(n-i)!\)
\(G[n]=\sum_{i=1}^{n}F[i]*G[n-i]*{i\over n}\)
ln的过程即由G->F,直接反过来可得:
\(F[n]=G[n]-\sum_{i=1}^{n-1}F[i]*G[n-i]*{i \over n}\)
Code:
#include<bits/stdc++.h>
#define fo(i, x, y) for(int i = x, B = y; i <= B; i ++)
#define ff(i, x, y) for(int i = x, B = y; i < B; i ++)
#define fd(i, x, y) for(int i = x, B = y; i >= B; i --)
#define ll long long
#define pp printf
#define hh pp("\n")
using namespace std;
const int N = 3e5 + 5;
int n, k, mo;
ll fac[N], nf[N];
ll ksm(ll x, ll y) {
ll s = 1;
for(; y; y /= 2, x = x * x % mo)
if(y & 1) s = s * x % mo;
return s;
}
ll C(int n, int m) {
ll s = 1;
fo(i, n - m + 1, n) s = s * i % mo;
s = s * nf[m] % mo;
return s;
}
ll ans;
const int nm = (1 << 17) + 5;
#define low(x) (x & -(x))
int g[nm * 4];
ll a[18][nm], f[2][18][nm]; int o;
void fwt(ll *a, int n) {
for(int i = 1; i < n; i *= 2) for(int j = 0; j < n; j += 2 * i)
ff(k, 0, i) a[i + j + k] += a[j + k];
ff(i, 0, n) a[i] %= mo;
}
int tp, aw[21];
int main() {
freopen("megalovania.in", "r", stdin);
freopen("megalovania.out", "w", stdout);
scanf("%d %d %d", &n, &k, &mo);
if(n & 1) {
pp("0\n"); return 0;
}
fac[0] = 1; fo(i, 1, n) fac[i] = fac[i - 1] * i % mo;
nf[n] = ksm(fac[n], mo - 2); fd(i, n, 1) nf[i - 1] = nf[i] * i % mo;
ff(i, 1, 1 << 19) g[i] = g[i - low(i)] + 1;
tp = g[n]; int cw = 0;
fo(j, 0, 18) if(n >> j & 1) {
aw[j] = 1 << (cw ++);
}
fo(i, 1, n) if((i & n) == i) {
int ni = 0;
fo(j, 0, 18) if(i >> j & 1) ni += aw[j];
a[g[i]][ni] = nf[i];
}
fo(i, 1, tp) fwt(a[i], 1 << tp);
fo(i, 1, tp) ff(j, 0, 1 << tp) f[o][i][j] = a[i][j];
int mx = (1 << tp) - 1;
fo(i, 1, tp) {
memset(f[!o], 0, sizeof f[!o]);
if(i != tp) {
fo(u, i, tp) fo(v, 1, tp - u) ff(j, 0, 1 << tp) if(f[o][u][j] && a[v][j])
f[!o][u + v][j] += f[o][u][j] * a[v][j],
f[!o][u + v][j] > 9e18 ? f[!o][u + v][j] %= mo : 0;
}
ll F = 0;
ff(j, 0, 1 << tp) F += f[o][tp][j] * (g[j ^ mx] % 2 ? -1 : 1);
F %= mo;
ans += F * C(k, i) % mo * fac[n] % mo;
o = !o;
fo(u, 0, tp) ff(j, 0, 1 << tp) f[o][u][j] >= mo ? f[o][u][j] %= mo : 0;
}
ans = (ans % mo + mo) % mo;
pp("%lld\n", ans);
}
CF838C(博弈+FWT子集卷积+多项式ln、exp)的更多相关文章
- Comet Contest#11 F arewell(DAG计数+FWT子集卷积)
传送门. 题解: 4月YY集训时做过DAG计数,和这个基本上是一样的,但是当时好像直接暴力子集卷积,不然我省选时不至于不会,这个就多了个边不选的概率和子集卷积. DAG计数是个套路来的,利用的是DAG ...
- CF914G Sum the Fibonacci (快速沃尔什变换FWT + 子集卷积)
题面 题解 这是一道FWT和子集卷积的应用题. 我们先设 cnt[x] 表示 Si = x 的 i 的数量,那么 这里的Nab[x]指满足条件的 Sa|Sb=x.Sa&Sb=0 的(a,b)二 ...
- 【XSY2730】Ball 多项式exp 多项式ln 多项式开根 常系数线性递推 DP
题目大意 一行有\(n\)个球,现在将这些球分成\(k\) 组,每组可以有一个球或相邻两个球.一个球只能在至多一个组中(可以不在任何组中).求对于\(1\leq k\leq m\)的所有\(k\)分别 ...
- 【学习笔记】fwt&&fmt&&子集卷积
前言:yyb神仙的博客 FWT 基本思路:将多项式变成点值表达,点值相乘之后再逆变换回来得到特定形式的卷积: 多项式的次数界都为\(2^n\)的形式,\(A_0\)定义为前一半多项式(下标二进制第一位 ...
- @总结 - 2@ 位运算卷积/子集卷积 —— FWT/FMT
目录 @0 - 参考资料@ @1 - 异或卷积概念及性质@ @2 - 快速沃尔什正变换(异或)@ @3 - 快速沃尔什逆变换(异或)@ @4 - 与卷积.或卷积@ @5 - 参考代码实现@ @6 - ...
- CF914G Sum the Fibonacci FWT、子集卷积
传送门 一道良心的练习FWT和子集卷积的板子-- 具体来说就是先把所有满足\(s_a \& s_b = 0\)的\(s_a \mid s_b\)的值用子集卷积算出来,将所有\(s_a \opl ...
- CF 914 G Sum the Fibonacci —— 子集卷积,FWT
题目:http://codeforces.com/contest/914/problem/G 其实就是把各种都用子集卷积和FWT卷起来算即可: 注意乘 Fibonacci 数组的位置: 子集卷积时不能 ...
- luogu P6097 子集卷积 FST FWT
LINK:子集卷积 学了1h多 终于看懂是怎么回事了(题解写的不太清楚 翻了好几篇博客才懂 一个需要用到的性质 二进制位为1个数是i的二进制数s 任意两个没有子集关系.挺显然. 而FST就是利用这个性 ...
- [模板]多项式全家桶小记(求逆,开根,ln,exp)
前言 这里的全家桶目前只包括了\(ln,exp,sqrt\).还有一些类似于带余数模,快速幂之类用的比较少的有时间再更,\(NTT\)这种前置知识这里不多说. 还有一些基本的导数和微积分内容要了解,建 ...
随机推荐
- css 实现文本换行及显示不下隐藏显示省略号
CSS文本超出2行就隐藏并且显示省略号 转载:https://www.cnblogs.com/wyaocn/p/5830364.html 今天做东西,遇到了这个问题,百度后总结得到了这个结果. 首 ...
- 在Eclipse上安装Spring Tool Suite
. 不装IDE会没有Spring bean configure file Spring Tool Suite是一个基于Eclipse IDE开发环境中的用于开发Spring应用程序的工具,提供了开箱即 ...
- hdu 5792 线段树+离散化+思维
题目大意: Given a sequence A with length n,count how many quadruple (a,b,c,d) satisfies: a≠b≠c≠d,1≤a< ...
- war包里面文件的修改方式
1 将war包移动到一个干净的路径下,使用 jar xvf ROOT.war 命令将war进行解压操作 2 修改相应的文件内容,修改想要修改的文件,比如web.xml 3 使用 j ...
- 深入理解Magento - 第五章 Magento资源配置
对于任何一个更新频繁的项目来说,保持开发环境和生产环境的数据库同步是件很头疼的事情.Magento提供了一套系统,用版本化的资源迁移脚本来解决这个问题. 上一章,我们为 Helloworld Blog ...
- [NOIP模拟测试7]visit 题解(组合数学+CRT+Lucas定理)
Orz 因为有T的限制,所以不难搞出来一个$O(T^3)$的暴力dp 但我没试 据说有30分? 正解的话显然是组合数学啦 首先$n,m$可能为负,但这并没有影响, 我们可以都把它搞成正的 即都看作向右 ...
- 数据结构学习笔记——顺序数组1
线性表最简单的刚开始就是顺序存储结构,我是看着郝斌的视频一点一点来的,严蔚敏的书只有算法,没有具体实现,此笔记是具体的实现 为什么数据结构有ADT呢,就是为了满足数据结构的泛性,可以在多种数据类型使用 ...
- Python中练习题关于内置函数的getattr,setattr问题
执行一下代码的结果是? class A: def __init__(self,a,b,c): self.x = a+b+c a = A(1,2,3) b = getattr(a,'x') setatt ...
- java基础集合底层介绍
ArrayList.Vector.HashMap.HashTable.HashSet的默认初始容量.加载因子.扩容增量 这里要讨论这些常用的默认初始容量和扩容的原因是: 当底层实现涉及到扩容时,容器或 ...
- git分布式版本控制系统权威指南学习笔记(六):git reset、get stash、git checkout总结
文章目录 1. 概述 2. 如何把修改暂存起来,留着以后使用? 2.1 使用场景 2.2 git stash 暂存进度 2.3 查看进度 2.4 恢复进度 3. 如何撤销工作区的修改? 4. 如何把暂 ...