CodeForces 1408I Bitwise Magic
题意
给定三个整数 \(n,k,c\) 和一个长度为 \(n\) 的序列 \(a\),保证 \(a_i\) 互不相同。可以操作 \(k\) 次,每次随机选择一个 \(a_i\) 变成 \(a_i-1\)。问最后的序列异或和为 \(0,\cdots 2^{c}-1\) 的概率。
\(\texttt{Data Range:}k,c\leq 16,k\leq a_i\leq 2^c-1,n\leq 2^{c}-k\)
题解
先来看一个显而易见的结论:对于 \(x\leq 2^c-1\),本质不同的 \(k\) 元组 \((x\oplus(x-1),x\oplus(x-2),\cdots,x\oplus(x-k))\) 的个数大约是 \(O(ck)\) 的。
首先注意到 \(x\oplus(x-1)\) 这个东西的取值只能是 \(2^t-1\) 的形式,其中 \(t=\log\operatorname{lowbit}(x)+1\)。考虑分类讨论。
如果 \(t>\log k\),因为 \(x\oplus (x-k)=(x\oplus (x-1))\oplus((x-1)\oplus(x-2))\cdots\),那么比 \(t\) 高的位不受影响,比 \(t\) 低的位因为是从 \(2^t-1\) 开始一个一个减的,与 \(x\) 无关,所有只有 \(O(c)\) 种取值。
如果 \(t\leq\log k\),那么这东西的取值只与 \(\log k\) 位往上走第一个 \(1\) 的位置和这 \(\log k\) 位的取值相关,所以取值为 \(O(c2^{\log k})=O(ck)\) 的。
经暴力计算可得 \(c=k=16\) 的时候只有 \(192\) 种本质不同的 \(k\) 元组。
由于直接数不好数,这里我们考虑每一次操作怎么改变答案的。容易看出如果对 \(a_i\) 操作 \(j\) 次的话会给原来的答案异或上 \(a_i\oplus (a_i-j)\)。
这个时候可以数一下本质不同操作序列的个数。由于操作序列随机排列是本质相同的,所以需要使用 EGF。为了方便,这里设 \(d_{i,j}=a_i\oplus(a_i-j)\),那么位置 \(i\) 的 EGF 为
\]
这里 \(x\) 枚举的是这个位置的值,\(y\) 枚举的是操作次数。将每个位置的这些东西乘起来得到总共的 EGF:
\]
其中 \(x\) 这个维度为异或卷积,\(y\) 为加法卷积。那么 \(v![x^u][y^v]\) 就表示操作了 \(v\) 次之后使得答案为 \(u\oplus a_1\oplus\cdots\oplus a_n\) 的方案数。注意到操作顺序不影响操作结果,在 EGF 的过程中去掉了这个影响,在最后统计的时候要乘回来。
考虑如何简化计算。对于每一个本质不同的 \(k\) 元组 \((x\oplus(x-1),x\oplus(x-2),\cdots,x\oplus(x-k))\) 来说,它对应的 EGF 是 \(x\) 操作若干次之后对答案的影响。于是我们可以设 \(G_i(x,y)\) 为第 \(i\) 中本质不同的 \(k\) 元组对应的 EGF,\(r_i\) 为出现次数,于是也可以这么表示 \(F\):
\]
这个时候如果采用 \(O(k^2)\) 暴力先 \(\ln\) 再 \(\exp\) 求快速幂的话复杂度为 \(O(2^cck^3)\)。如果使用牛顿迭代的话因为常数原因,而且多项式次数较小跑得还没有暴力快。
对于某个 \(k\) 元组来说,考虑钦定一个 \(y\),再对 \(x\) 这个维度做 FWT。因为钦定了 \(y\) 的话只会有一个 \(x\) 的系数是形如 \(\frac{y^k}{k!}\) 的。根据 FWT 的相关理论,做完 FWT 之后中每一项都是形如 \(\pm\frac{y^k}{k!}\) 的。
这个时候就可以将每一个 \(k\) 元组对应到一个 \(1\) 和 \(-1\) 的序列上去,这个序列可以状压。将状压之后的东西放在一起快速幂即可。
代码
#include<bits/stdc++.h>
#pragma GCC optimize("Ofast,unroll-loops")
#define pb emplace_back
#define popc __builtin_popcount
using namespace std;
typedef int ll;
typedef long long int li;
typedef vector<ll> vi;
const ll MAXN=65541,MOD=998244353;
map<vi,ll>mp;
ll n,kk,c,xorv,tot,fct,d,tp;
ll x[MAXN],invl[MAXN],finv[MAXN],f[MAXN],cnt[MAXN<<1];
ll st[201],sm[201],tmp[21],tmp2[21],tmp3[21];
li tmp4[21];
vi v[MAXN];
inline ll read()
{
register ll num=0,neg=1;
register char ch=getchar();
while(!isdigit(ch)&&ch!='-')
{
ch=getchar();
}
if(ch=='-')
{
neg=-1;
ch=getchar();
}
while(isdigit(ch))
{
num=(num<<3)+(num<<1)+(ch-'0');
ch=getchar();
}
return num*neg;
}
inline ll qpow(ll base,ll exponent)
{
ll res=1;
while(exponent)
{
if(exponent&1)
{
res=(li)res*base%MOD;
}
base=(li)base*base%MOD,exponent>>=1;
}
return res;
}
inline void ln(ll fd,ll *f,ll *res)
{
li r;
res[0]=0;
for(register int i=1;i<fd;i++)
{
r=0;
for(register int j=1;j<i;j++)
{
r+=(li)f[j]*res[i-j]%MOD;
}
res[i]=((li)i*f[i]%MOD-r%MOD+MOD)%MOD;
}
for(register int i=1;i<fd;i++)
{
res[i]=(li)res[i]*invl[i]%MOD;
}
}
inline void exp(ll fd,ll *f,ll *res)
{
li r;
res[0]=1;
for(register int i=1;i<fd;i++)
{
r=0,f[i]=(li)f[i]*i%MOD;
for(register int j=0;j<i;j++)
{
r+=(li)f[j+1]*res[i-j-1]%MOD;
}
res[i]=r%MOD*invl[i]%MOD;
}
}
int main()
{
n=read(),kk=read(),c=read(),invl[0]=invl[1]=finv[0]=finv[1]=fct=1;
for(register int i=2;i<65536;i++)
{
invl[i]=(MOD-(li)(MOD/i)*invl[MOD%i]%MOD)%MOD;
finv[i]=(li)finv[i-1]*invl[i]%MOD;
}
for(register int i=1;i<=n;i++)
{
xorv^=(x[i]=read());
for(register int j=0;j<=kk;j++)
{
v[i].pb(x[i]^(x[i]-j));
}
mp[v[i]]++;
}
for(auto i:mp)
{
v[++tot]=i.first,sm[tot]=i.second;
}
for(register int i=2;i<=kk;i++)
{
fct=(li)fct*i%MOD;
}
for(register int s=0;s<(1<<c);s++)
{
for(register int i=1;i<=tot;i++)
{
d=0;
for(register int j=0;j<=kk;j++)
{
d|=((popc(s&v[i][j])&1)<<j);
}
!cnt[d]?st[++tp]=d:1,cnt[d]+=sm[i];
}
memset(tmp,0,sizeof(tmp)),tmp[0]=1;
for(register int i=1;i<=tp;i++)
{
for(register int j=0;j<=kk;j++)
{
tmp2[j]=(st[i]&(1<<j))?MOD-finv[j]:finv[j];
}
ln(kk+1,tmp2,tmp3);
for(register int j=0;j<=kk;j++)
{
tmp3[j]=(li)tmp3[j]*cnt[st[i]]%MOD;
}
exp(kk+1,tmp3,tmp2),memset(tmp4,0,sizeof(tmp4));
for(register int j=0;j<=kk;j++)
{
for(register int k=0;k<=kk-j;k++)
{
tmp4[j+k]+=(li)tmp2[j]*tmp[k];
}
}
for(register int j=0;j<=kk;j++)
{
tmp[j]=tmp4[j]%MOD;
}
cnt[st[i]]=0;
}
tp=0,f[s]=(li)tmp[kk]*fct%MOD;
}
for(register int i=1;i<(1<<c);i<<=1)
{
for(register int p=0;p<(1<<c);p+=i<<1)
{
for(register int j=p;j<p+i;j++)
{
d=f[j],f[j]=(f[j]+f[j+i])%MOD,f[j+i]=(d-f[j+i]+MOD)%MOD;
}
}
}
d=(li)qpow(1<<c,MOD-2)*qpow(n,MOD-1-kk)%MOD;
for(register int i=0;i<(1<<c);i++)
{
printf("%d ",(li)f[i^xorv]*d%MOD);
}
}
CodeForces 1408I Bitwise Magic的更多相关文章
- Codeforces 1408I - Bitwise Magic(找性质+集合幂级数)
Codeforces 题面传送门 & 洛谷题面传送门 Yet another immortal D1+D2 I %%%%%% 首先直接统计肯定是非常不容易的,不过注意到这个 \(k\) 非常小 ...
- Codeforces 424 C. Magic Formulas
xor是满足交换律的,展开后发现仅仅要能高速求出 [1mod1....1modn],....,[nmod1...nmodn]的矩阵的xor即可了....然后找个规律 C. Magic Formulas ...
- codeforces 922 B. Magic Forest(枚举、位运算(异或))
题目链接:点击打开链接 Imp is in a magic forest, where xorangles grow (wut?) A xorangle of order n is such a no ...
- 【Codeforces 1110E】Magic Stones
Codeforces 1110 E 题意:给定两个数组,从第一个数组开始,每次可以挑选一个数,把它变化成左右两数之和减去原来的数,问是否可以将第一个数组转化成第二个. 思路: 结论:两个数组可以互相转 ...
- codeforces 710C C. Magic Odd Square(构造)
题目链接: C. Magic Odd Square Find an n × n matrix with different numbers from 1 to n2, so the sum in ea ...
- CodeForces 628 D Magic Numbers 数位DP
Magic Numbers 题意: 题意比较难读:首先对于一个串来说, 如果他是d-串, 那么他的第偶数个字符都是是d,第奇数个字符都不是d. 然后求[L, R]里面的多少个数是d-串,且是m的倍数. ...
- CodeForces 779E Bitwise Formula
位运算,枚举. 按按分开计算,枚举$?$是$0$还是$1$,分别计算出$sum$,然后就可以知道该位需要填$1$还是$0$了. #include<map> #include<set& ...
- 【Codeforces 1117C】Magic Ship
[链接] 我是链接,点我呀:) [题意] 题意 [题解] 我们可以把这个行船的过程分解成两个过程 1.船经过时间t被风吹到了某个地方 2.船用这t时间尝试到达终点(x2,y2) 会发现如果时间t能最终 ...
- CodeForces 778B - Bitwise Formula
题意: 选择一个 m 位的二进制数字,总分为 n 个算式的答案之和.问得到最低分和最高分分别应该取哪个二进制数字 分析: 因为所有数字都是m位的,高位的权重大于低位 ,我们就从高到低考虑 ans 的每 ...
随机推荐
- GZip 压缩解压 工具类 [ GZipUtil ]
片段 1 片段 2 pom.xml <dependency> <groupId>commons-codec</groupId> <artifactId> ...
- Redis小记(一)
1.redis的数据结构 (1)动态字符串(SDS) redis自身构建了一个简单动态字符串的抽象类型,SDS,在redis里,包含字符串的键值对在底层都是由SDS来实现的. 除了用来保存数据库的字符 ...
- LeetCode刷题总结-DFS、BFS和回溯法篇
本文总结LeetCode上有关深度优先搜索(DFS).广度优先搜索(BFS)和回溯法的算法题,推荐刷题总数为13道.具体考点分析如下图: 一.深度优先搜索 1.字符匹配问题 题号:301. 删除无效的 ...
- javascript内置对象的innerText、innerHTML、join方法的认识
innerText语法规范:HTMLElement.innerText = string ;//后面的赋值是一个字符串形式 innerText是一个非标准形式,不识别HTML标签 返回值会去除空格和换 ...
- 【随笔】菜刀(代码执行)函数和命令执行函数详解及Getshell方法
代码执行函数 VS 命令执行函数 一直想整理这两块的内容,但是一直没时间弄,直到前两天碰上一个写入了菜刀马但是死活连不上菜刀的站,顿时不知道怎么继续了,所以就趁这个机会整理了一下代码执行函数怎么get ...
- PADS Layout VX.2.3 修改层名
操作系统:Windows 10 x64 工具1:PADS Layout VX.2.3 点击菜单Setup > Layer Definition... 在Layers Setup窗口中,选择相应的 ...
- RTKLIB的主要功能
RTKLIB是全球导航卫星系统GNSS(global navigation satellite system)的标准&精密定位开源程序包,RTKLIB由日本东京海洋大学(Tokyo Unive ...
- Windows7 提示“无法访问您可能没有权限使用网络资源”的解决办法
大家经常会碰到,电脑A(Windows7)访问局域网打印机的时候出现提示"无法访问你可能没有权限使用网络资源",导致无法正常使用打印机. 那么出现这种情况该如何解决呢? 解决方法: ...
- Python+Appium自动化测试(5)-appium元素定位常用方法
对于Android而言,查找appUI界面元素属性的工具有三种:appium desktop,uiautomatorviewer.bat,weditor.之前已经介绍过了weditor的使用,这里我将 ...
- 如何修改或新增visual studio 的模板
在 visual studio 中添加模板,我这里是新增mvc.net的模板 vs2017在文件夹=>(举例说明,请替换为相应的安装目录) D:\Program Files (x86)\Micr ...