[uoj272]石家庄的工人阶级队伍比较坚强
假设$x,y\in \{0,1,2\}$,则$x$能赢$y$(根据题中定义)当且仅当$x-y\equiv 1(mod\ 3)$
定义$\ominus$为两数3进制下不退位的减法,$S_{x}$表示$x$在3进制下1的个数,则$u=W(x,y)=S_{x\ominus y}$,类似地,有$v=W(y,x)=S_{y\ominus x}$
记$B_{x,y}=b_{S_{x\ominus y},S_{y\ominus x}}$,令$k=x\ominus y$,根据$\ominus$的性质,有$k\ominus 0=x\ominus y$以及$0\ominus k=y\ominus x$,代入后就可以得到$B_{x,y}=b_{S_{k\ominus 0},S_{0\ominus k}}=B_{k,0}$,再记$g_{k}=B_{k,0}$,可以预处理出来
原题也就是$f_{i,x}=\sum_{y=0}^{3^{m}-1}g_{x\ominus y}f_{i-1,y}$,再令$\oplus$为3进制下按位加法,有$(x\ominus y)\oplus y=x$,也就是一个$\oplus$的卷积,记这个卷积为$\otimes$运算,有$f_{i}=g\otimes f_{i-1}$
根据卷积的结合律,有$f_{t}=g^{t}\otimes f_{0}$(其中$g^{t}$也是上面的$\otimes$),也就是要快速计算$\otimes$运算
我们直接来考虑原问题的一个拓展,即令$\oplus$为$B$进制下不进位加法,$\otimes$为$\oplus$卷积($B$是一个较小的数),如何对两个序列快速计算$\otimes$这个运算
为了方便起见,不妨假设序列长度$n=B^{k}$,不足可以补0
对于两个序列$a_{i}$和$b_{i}$,考虑构造一个$n\times n$的矩阵$A_{i,j}$(将序列看作一个$1\times n$的矩阵),令$a'=aA$,$b'=bA$,再令$c'=a'*b'$(这里的*指对应位置相乘),最后$c=c'A^{-1}$
$\forall n=B^{k}(k\ge 1)$,若矩阵$A$满足以下两个条件,则最终有$c=a\otimes b$:
1.其左上角$B\times B$的矩阵在$n=B$时满足$c=a\otimes b$
2.$A_{i,j}=A_{\lfloor\frac{i}{B}\rfloor,\lfloor\frac{j}{B}\rfloor}A_{i\ mod\ B,j\ mod\ B}$,且$A^{-1}$具有同样性质
证明如下——
注意到当$n=B$时,左上角$B\times B$的矩阵即为$A$本身,那么由条件1可知其正确
归纳$n=B^{k}(k\ge 1)$时正确,考虑$n=B^{k+1}$时正确性:
对于每一个$0\le i<B^{k+1}$,都可以被表示为$i_{0}B+i_{1}$(其中$0\le i_{0}<B^{k}$,$0\le i_{1}<B$)
对于$a_{i}$和$b_{i}$,代入式子即有
$$
c_{i}=\sum_{j=0}^{B^{k+1}-1}c'_{j}A^{-1}_{j,i}=\sum_{j_{1}=0}^{B-1}\sum_{j_{0}=0}^{B^{k}-1}c'_{j_{0}B+j_{1}}A^{-1}_{j_{0}B+j_{1},i_{0}B+i_{1}}=\sum_{j_{1}=0}^{B-1}A^{-1}_{j_{1},i_{1}}\sum_{j_{0}=0}^{B^{k}-1}c'_{j_{0}B+j_{1}}A^{-1}_{j_{0},i_{0}}
$$
考虑$c'_{i}$,同样可以代入得到
$$
c'_{i}=a'_{i}b'_{i}=(\sum_{j_{1}=0}^{B-1}A_{j_{1},i_{1}}\sum_{j_{0}=0}^{B^{k}-1}a_{j_{0}B+j_{1}}A_{j_{0},i_{0}})(\sum_{j_{1}=0}^{B-1}A_{j_{1},i_{1}}\sum_{j_{0}=0}^{B^{k}-1}b_{j_{0}B+j_{1}}A_{j_{0},i_{0}})
$$
(关于$a'_{i}$和$b'_{i}$用$a_{i}$和$b_{i}$表达,与$c_{i}$用$c'_{i}$表达相同,将$A^{-1}$改为$A$即可)
对$a_{i}$和$b_{i}$分别构造出$B$个序列,即$d_{j_{0},i}=a_{iB+j_{0}}$以及$e_{j_{0},i}=b_{iB+j_{0}}$,考虑$d_{x}$和$e_{y}$分别作为$a_{i}$和$b_{i}$通过前面的方式计算,可以算出$c'$,记作$f'_{x,y}$,即有
$$
f'_{x,y,i}=(\sum_{j=0}^{B^{k}-1}d_{x,j}A_{j,i})(\sum_{j=0}^{B^{k}-1}e_{y,j}A_{j,i})=(\sum_{j=0}^{B^{k}-1}a_{jB+x}A_{j,i})(\sum_{j=0}^{B^{k}-1}b_{jB+y}A_{j,i})
$$
可以发现这个式子与上面的$c'_{i}$有关,具体来说即
$$
c'_{i}=\sum_{x=0}^{B-1}A_{x,i_{1}}\sum_{y=0}^{B-1}A_{y,i_{1}}f'_{x,y,i_{0}}
$$
整体将$c'_{i}$的式子代入$c_{i}$中,也就得到了
$$
c_{i}=\sum_{j_{1}=0}^{B-1}A^{-1}_{j_{1},i_{1}}\sum_{j_{0}=0}^{B^{k}-1}A^{-1}_{j_{0},i_{0}}\sum_{x=0}^{B-1}A_{x,j_{1}}\sum_{y=0}^{B-1}A_{y,j_{1}}f'_{x,y,j_{0}}=\sum_{j_{1}=0}^{B-1}A^{-1}_{j_{1},i_{1}}\sum_{x=0}^{B-1}A_{x,j_{1}}\sum_{y=0}^{B-1}A_{y,j_{1}}\sum_{j_{0}=0}^{B^{k}-1}A^{-1}_{j_{0},i_{0}}f'_{x,y,j_{0}}
$$
显然最后一个式子也就是$f'_{x,y}A^{-1}$,记作$f_{x,y}$,根据归纳有$f_{x,y}=d_{x}\otimes e_{y}$,联系其定义即
$$
f_{x,y,i}=\sum_{0\le p_{0},q_{0}<B^{k},p_{0}\oplus q_{0}=i}d_{x,p_{0}}e_{y,q_{0}}
$$
再次代入$c_{i}$中,即
$$
c_{i}=\sum_{j_{1}=0}^{B-1}A^{-1}_{j_{1},i_{1}}\sum_{x=0}^{B-1}A_{x,j_{1}}\sum_{y=0}^{B-1}A_{y,j_{1}}\sum_{0\le p_{0},q_{0}<B^{k},p_{0}\oplus q_{0}=i_{0}}d_{x,p_{0}}e_{y,q_{0}}=\sum_{0\le p_{0},q_{0}<B^{k},p_{0}\oplus q_{0}=i_{0}}\sum_{j_{1}=0}^{B-1}A^{-1}_{j_{1},i_{1}}\sum_{x=0}^{B-1}A_{x,j_{1}}d_{x,p_{0}}\sum_{y=0}^{B-1}A_{y,j_{1}}e_{y,q_{0}}
$$
对于$p_{0}$和$q_{0}$,构造$u_{i}=d_{i,p_{0}}$以及$v_{i}=e_{i,q_{0}}$,将两者作为$a_{i}$和$b_{i}$进行计算,关于$x$的枚举也就是算出$u'_{j_{1}}$,第二个关于$y$的枚举也就是$v'_{j_{1}}$,两者对应位置相乘,也就是$c'_{j_{1}}$,再乘上前面的$A_{j_{1},i_{1}}^{-1}$,也就是$c_{i_{1}}$
(这里的$c'_{j_{1}}$和$c_{i_{1}}$指代入$u_{i}$和$v_{i}$后用前面的方式计算得到,与之前的$c'_{i}$与$c_{i}$无关)
进一步的,根据归纳有$c_{i_{1}}=(u\otimes v)_{i_{1}}=\sum_{0\le p_{1},q_{1}<B,p_{1}\oplus q_{1}=i_{1}}u_{p_{1}}v_{q_{1}}$,代入即
$$
c_{i}=\sum_{0\le p_{0},q_{0}<B^{k},p_{0}\oplus q_{0}=i_{0}}\sum_{0\le p_{1},q_{1}<B,p_{1}\oplus q_{1}=i_{1}}a_{p_{0}B+p_{1}}b_{q_{0}B+q_{1}}=\sum_{0\le p,q<B^{k+1},p\oplus q=i}a_{p}b_{q}=(a\otimes b)_{i}
$$
(最后就利用到了$\oplus$是按位运算的)
确定矩阵$A$的条件后,我们还要具体的构造出一个矩阵$A$,通过矩阵左上角$B\times B$的部分就可以根据第二个条件唯一确定$A$了,也就是如何构造$n=B$时的矩阵
不难发现这就是一个幂次对$B$取模的加法卷积,联系FFT,记$\omega=\cos\frac{2\pi}{B}+\sin\frac{2\pi}{B}i$,取$A_{i,j}=\omega^{ij}$,逆矩阵将则令$A^{-1}_{i,j}=\frac{\omega^{-(ij)}}{B}$,下面来证明一下:
当我们确定了$A_{i,j}=\omega^{i}$,相当于将$a_{i}$看作一个$B$次多项式,求出其在$\omega^{i}$的值
根据余数定理,当我们知道一个多项式在$x=\omega^{i}$上的值,事实上也就是该多项式模$x-\omega^{i}$后的结果,而求出了所有$\omega^{i}$,那么也就知道了原多项式对$\prod_{i=0}^{B-1}(x-\omega^{i})$取模的结果
再将点值相乘, 也就确定了最终多项式对$\prod_{i=0}^{B-1}(x-\omega^{i})$取模后的结果
注意到$\omega$满足$\omega^{B}=1$且$\forall 1\le i<B,\omega^{i}\ne 1$,则$\prod_{i=0}^{B-1}(x-\omega^{i})=x^{B}-1$,而$x^{n}\equiv x^{n\ mod\ B}(mod\ x^{B}-1)$,因此恰好也就求出了下标对$B$取模的卷积结果
关于$\prod_{i=0}^{B-1}(x-\omega^{i})=x^{B}-1$,由于其可以看作$B$对点值$\{x=\omega^{i},y=0\}$,且每一个$x$各不相同,由此恰好可以确定一个$B$次多项式,且$x^{B}-1$恰好满足此性质,因此即相等
然而,本题需要对$p$取模,如果用实数表示的误差无法解决,代入$B=3$,可得$\omega=\frac{\sqrt{3}}{2}i-\frac{1}{2}$
考虑题中关于$p$的限制:不存在正整数$x,y$满足$\frac{1}{x}+\frac{1}{y}=\frac{3}{p}$
若$p\equiv 0(mod\ 3)$,取$x=y=\frac{2p}{3}$即满足条件,因此$\frac{1}{3}$在模$p$意义下有意义,但并不能保证3在模$p$意义下有二次剩余,换言之$\sqrt{3}$不一定有意义($\frac{1}{2}$有意义也可以证,但不关心)
为了使系数为整数,考虑将$\omega$作为一个整体,显然每一个虚数与$a+b\omega$一一对应,同时根据$\omega^{3}=1$以及$\omega^{2}=-\omega-1$(这两个条件也就是根据$\prod_{i=0}^{B-1}(x-\omega^{i})=x^{B}-1$得到),当产生高次项也都可以降为一次来表示
最终答案必然是整数,因此$b=0$,即为$a$
另外,计算矩阵乘法可以利用条件2来做,以由$a$计算$a'$为例子,即
$$
a'_{i}=\sum_{j=0}^{B^{k}-1}a_{j}A_{j,i}=\sum_{j_{1}=0}^{B-1}A_{j_{1},i_{1}}\sum_{j_{0}=0}^{B^{k-1}-1}a_{j_{0}B+j_{1}}A_{j_{0},i_{0}}
$$
对于每一个$j_{1}$,后面也就是一个$B^{k-1}$规模的子问题(矩阵乘法),递归后将其求出后,再代入该式即可,这样单次矩乘时间复杂度为$o(kB^{k+1})$
由于要快速幂,总复杂度为$o((m+\log_{2}t)3^{m})$可以通过
补充一下与本题无关的一些事情:
$B=2$时这个问题就是FWT,且做法与其完全相同
当$B$足够大时即为FFT,但时间复杂度会退化为$o(n^{2})$
1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 600005
4 #define M 13
5 int n,m,t,mod,S[N],base[N][M],b[M][M];
6 struct Complex{
7 int a,b;
8 Complex(){
9 a=b=0;
10 }
11 Complex(int x){
12 a=x,b=0;
13 }
14 Complex(int x,int y){
15 a=x,b=y;
16 }
17 Complex operator + (const Complex &k)const{
18 return Complex((a+k.a)%mod,(b+k.b)%mod);
19 }
20 Complex operator * (const Complex &k)const{
21 int s=mod-1LL*b*k.b%mod;
22 return Complex((1LL*a*k.a+s)%mod,(1LL*a*k.b+1LL*b*k.a+s)%mod);
23 }
24 }inv3,A[3][3],invA[3][3],a[N],ans[N];
25 Complex pow(Complex n,int m){
26 Complex s=n,ans=Complex(1);
27 while (m){
28 if (m&1)ans=ans*s;
29 s=s*s;
30 m>>=1;
31 }
32 return ans;
33 }
34 void DFT(Complex *a){
35 Complex aa[3];
36 for(int i=0,s=1;i<m;i++,s*=3)
37 for(int j=0;j<n;j++)
38 if (!base[j][i]){
39 for(int k=0;k<3;k++)aa[k]=Complex();
40 for(int k=0;k<3;k++)
41 for(int l=0;l<3;l++)aa[k]=aa[k]+a[j+l*s]*A[l][k];
42 for(int k=0;k<3;k++)a[j+k*s]=aa[k];
43 }
44 }
45 void IDFT(Complex *a){
46 Complex aa[3];
47 for(int i=0,s=1;i<m;i++,s*=3)
48 for(int j=0;j<n;j++)
49 if (!base[j][i]){
50 for(int k=0;k<3;k++)aa[k]=Complex();
51 for(int k=0;k<3;k++)
52 for(int l=0;l<3;l++)aa[k]=aa[k]+a[j+l*s]*invA[l][k];
53 for(int k=0;k<3;k++)a[j+k*s]=aa[k];
54 }
55 }
56 int main(){
57 scanf("%d%d%d",&m,&t,&mod);
58 n=1;
59 for(int i=1;i<=m;i++)n*=3;
60 for(int i=0;i<n;i++){
61 S[i]=S[i/3]+(i%3==1);
62 base[i][0]=i%3;
63 for(int j=1;j<m;j++)base[i][j]=base[i/3][j-1];
64 }
65 int k=mod,phi=mod;
66 for(int i=2;i*i<=k;i++)
67 if (k%i==0){
68 phi=phi/i*(i-1);
69 while (k%i==0)k/=i;
70 }
71 if (k>1)phi=phi/k*(k-1);
72 inv3=pow(Complex(3),phi-1);
73 for(int i=0;i<3;i++)
74 for(int j=0;j<3;j++){
75 A[i][j]=pow(Complex(0,1),i*j);
76 invA[i][j]=pow(Complex(0,1),6-i*j)*inv3;
77 }
78 for(int i=0;i<n;i++){
79 scanf("%d",&k);
80 a[i]=Complex(k);
81 }
82 for(int i=0;i<=m;i++)
83 for(int j=0;j<=m-i;j++)scanf("%d",&b[i][j]);
84 for(int i=0;i<n;i++){
85 k=0;
86 for(int j=m-1;j>=0;j--)
87 if (!base[i][j])k=k*3;
88 else k=k*3+3-base[i][j];
89 ans[i]=Complex(b[S[i]][S[k]]);
90 }
91 DFT(a);
92 DFT(ans);
93 for(int i=0;i<n;i++)ans[i]=a[i]*pow(ans[i],t);
94 IDFT(ans);
95 for(int i=0;i<n;i++)printf("%d\n",ans[i].a);
96 }
[uoj272]石家庄的工人阶级队伍比较坚强的更多相关文章
- [清华集训2016]石家庄的工人阶级队伍比较坚强——三进制FWT
题目链接: [清华集训2016]石家庄的工人阶级队伍比较坚强 题目大意:有$n=3^m$个人玩石头剪刀布,共$t$轮游戏,每轮每个人要和包括自己的所有人各进行$m$次石头剪刀布.每个人在$m$轮中的决 ...
- UOJ272 [清华集训2016] 石家庄的工人阶级队伍比较坚强 【分治乘法】
题目分析: 首先不难注意到式子就是异或卷积,所以考虑用分治乘法推出优化方法.我们把一个整体$f$拆成$f-,f\pm,f+$,然后另一个拆成$g-,g\pm,g+$.这样做的好处是能更清楚的分析问题. ...
- UOJ272. 【清华集训2016】石家庄的工人阶级队伍比较坚强 [FWT]
UOJ 思路 很容易想到\(O(3^{3m}\log T)\)的暴力大矩乘,显然过不了. 我们分析一下每次转移的性质.题目给的转移方程是填表法,我们试着改成刷表法看看-- 发现好像没啥用. 注意到游戏 ...
- uoj#272. 【清华集训2016】石家庄的工人阶级队伍比较坚强
http://uoj.ac/problem/272 这题的式子形式是异或卷积的三进制推广,因此可以设计一个类似fwt的变换,这里需要一个三次单位根$w$,满足$w^3\%p==1$且$(1+w+w^2 ...
- 卷积理论 & 高维FWT学习笔记
之前做了那么多生成函数和多项式卷积的题目,结果今天才理解了优化卷积算法的实质. 首先我们以二进制FWT or作为最简单的例子入手. 我们发现正的FWT or变换就是求$\hat{a}_j=\sum_{ ...
- 位运算卷积-FWT
问题 给出两个幂级数 \(f,g\) ,求 \[ h=\sum _i\sum _jx^{i\oplus j}f_ig_j \] 其中 \(\oplus\) 是可拆分的位运算. 算法 由于位运算具有独立 ...
- Codechef November Challenge 2019 Division 1
Preface 这场CC好难的说,后面的都不会做QAQ 还因为不会三进制位运算卷积被曲明姐姐欺负了,我真是太菜了QAQ PS:最后还是狗上了六星的说,期待两(三)场之内可以上七星 Physical E ...
- NOIP提高模拟题 混乱的队伍
混乱的奶牛 Description 混乱的奶牛 [Don Piele, 2007] Farmer John的N(4 <= N <= 16)头奶牛中的每一头都有一个唯一的编号S_i (1 & ...
- 【编程题目】n 支队伍比赛,分别编号为 0,1,2。。。。n-1,已知它们之间的实力对比关系,
36.引用自网友:longzuo(运算)谷歌笔试: 19n 支队伍比赛,分别编号为 0,1,2....n-1,已知它们之间的实力对比关系,存储在一个二维数组 w[n][n]中,w[i][j] 的值代表 ...
随机推荐
- java 从零开始手写 RPC (04) -序列化
序列化 java 从零开始手写 RPC (01) 基于 socket 实现 java 从零开始手写 RPC (02)-netty4 实现客户端和服务端 java 从零开始手写 RPC (03) 如何实 ...
- 微服务架构理论&SpringCloud
一.什么是微服务? 微服务是一种程序架构模式,它提倡将单体应用程序划分成若干的小服务模块,服务之间互相协调.互相配合,为用户提供最终价值.每个服务运行在其独立的进程中,服务与服务间采用轻量级的通信机制 ...
- 1.2 Simple Code!(翻译)
Simple Code! 简洁编码 Playing football is very simple, but playing simple football is the hardest thing ...
- 【原创】Linux v4l2框架分析
背景 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 说明: Kernel版本: ...
- 关于评论区empty。。。
空荡荡的毫无人烟,博主希望路过的小哥哥/小姐姐(几率较小)留下些什么--
- 2021.10.9考试总结[NOIP模拟72]
T1出了个大阴间题 状压\(DP\),记当前状态的代价和与方案数.状态\(\Theta(2^nn)\),转移\(\Theta(n)\). 发现每个状态的最大值只会是所选集合的\(max\)或加一.于是 ...
- 2021.1.8 NKOJ 周赛总结
意料之中..... A:nkoj 3900 AC小程序 http://oi.nks.edu.cn/zh/Problem/Details/3900 A题比较简单,单独分析一下A和C,其实就是一个斐波那契 ...
- Envoy实现.NET架构的网关(三)代理GRPC
什么是GRPC gRPC是一种与语言无关的高性能远程过程调用 (RPC) 框架.gRPC 的主要好处是: 现代.高性能.轻量级的 RPC 框架. 契约优先的 API 开发,默认使用协议缓冲区,与语言无 ...
- python网站(持续更新)
python官网: https://www.python.org/ python文档:中文 https://docs.python.org/zh-cn/3/ pypi网站: https://pypi. ...
- hdu 5179 beautiful number(构造,,,,)
题意: 一个如果称作是漂亮数,当且仅当满足: 每一位上的数字是[1,9],从高到时低数字大小降序,且有di%dj=0(i<j) 例:931 给一个区间[L,R],问这个区间里有多少个漂亮数. 1 ...