[清华集训2016]石家庄的工人阶级队伍比较坚强——三进制FWT
题目链接:
题目大意:有$n=3^m$个人玩石头剪刀布,共$t$轮游戏,每轮每个人要和包括自己的所有人各进行$m$次石头剪刀布。每个人在$m$轮中的决策固定,即为这个人编号的长度为$m$的三进制(其中$0$表示剪刀、$1$表示石头、$2$表示布,不足$m$位用$0$补齐)。每个人有一个初始分数$f_{0,x}$,给出一个分数矩阵$b$,其中$b_{i,j}$表示赢了$i$局输了$j$局的得分,在第$i$轮结束后,第$x$个人的分数为$f_{i,x}=\sum\limits_{0\le y\le n}{ }f_{i-1,y}b_{u,v}$。其中$b_{u,v}$表示$x$与$y$石头剪刀布,$x$赢了$u$次,输了$v$次的得分。求$t$轮后每个人的得分。
首先因为每个人的决策是固定的,所以转移关系也是恒定的,我们设它是一个矩阵$B$,其中$B_{i,j}$表示$i$与$j$游戏时$i$获得的分数。那么要求的就是$f_{n}=f_{0}B^n$。
我们定义三进制不进位加法为$\oplus$,不退位减法为$\ominus$,他们互为逆运算(与二进制下的异或类似)。
那么对于$\forall k<3^m,B_{i,j}=B_{i\oplus k,j\oplus k}$,同理$B_{i,j}=B_{i\ominus j,0}$。而这个结论也可以推广到$B^n$,即$\forall k<3^m,B_{i,j}^{n}=b_{i\ominus j,0}^{n}$。
那么$f_{n,i}=\sum\limits_{k=0}^{3^m-1}f_{0,k}B_{k,i}^n=\sum\limits_{k=0}^{3^m-1}f_{0,k}B_{0,i\ominus k}^n=\sum\limits_{x\oplus y=i}f_{0,x}B_{0,y}^n$
所以,我们只需要$B$矩阵的第一行就够了,又因为
$B_{0,i}^n=\sum\limits_{k=0}^{3^m-1}B_{0,k}^{n-1}B_{k,i}=\sum\limits_{k=0}^{3^m-1}B_{0,k}^{n-1}B_{0,i\ominus k}=\sum\limits_{x\oplus y=i}B_{0,x}^{n-1}B_{0,y}$
所以只需要将$B_{0}$做$n$次卷积然后和$f_{0}$做一次卷积即可得到答案。
也就是说我们需要找到一个三进制不进位加法卷积,这种模意义下的卷积也叫循环卷积。
其实在我们熟悉的卷积中就有类似的存在——FWT的异或卷积
可以发现FWT异或卷积实际上就是二进制不进位加法卷积。
我们先来研究一下FWT异或卷积:
设$bitcount(i)$表示$i$二进制中$1$的个数。
因为$bitcount(i\&k)$的奇偶性异或$bitcount(j\&k)$的奇偶性等于$bitcount((i\oplus j)\&k)$的奇偶性
那么我们就可以构造出正变换$F(k)=\sum(-1)^{bitcount(i\&k)}f(i)$
可以发现上述式子中的$bitcount(i)$也就是$i$的二进制每一位数的和,而$\&$就是二进制下的不进位乘法、$\oplus$是二进制下不进位加法
那么我们同样可以将这些扩展到三进制中,即$bitcount_{3}(i)$表示$i$的三进制每一位数的和、$\&_{3}$表示三进制下的不进位乘法、$\oplus_{3}$表示三进制下的不进位加法
而上述结论在三进制下也依旧成立
即$(bitcount_{3}(i\&_{3}k)\%3)\oplus_{3}(bitcount_{3}(i\&_{3}k)\%3)=bitcount((i\oplus_{3}j)\&_{3}k)$
那么现在只需要找到一个能代替上式中$-1$的数就能完成这个三进制不进位加法卷积了,而这个数$w$要满足$w^{i}=w^{i\%3}$,所以只要用三次单位根就行了($FWT$中的$-1$也就是二次单位根)!
这里为了方便可以将所有复数都表示成$a+bw$,因为$w^2+w+1=0$,所以$w^2=-w-1$。
对于两个复数相乘就是$(a+bw)*(c+dw)=ac+(bc+ad)w+bd(-w-1)=(ac-bd)+(ad+bc-bd)w$
因为最后要乘上$3^m$的逆元,所以要求$3^m$与$p$互质。
假设$p$有$3$这个质因子且$k=\frac{p}{3}$,那么$\frac{1}{k+1}+\frac{1}{k(k+1)}=\frac{1}{k}=\frac{3}{p}$,与题面矛盾,因此保证了$3^m$有逆元。
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<vector>
#include<bitset>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
#define ull unsigned long long
using namespace std;
int n,m,t,mod;
int a[20][20];
int x[600010];
int y[600010];
struct miku
{
int x,y;
miku(){}
miku(int X,int Y){x=X,y=Y;}
miku s(){return miku((mod-y)%mod,(x-y+mod)%mod);}
miku t(){return miku((y-x+mod)%mod,(mod-x)%mod);}
miku operator +(const miku &res){return miku((x+res.x)%mod,(y+res.y)%mod);}
miku operator -(const miku &res){return miku((x-res.x+mod)%mod,(y-res.y+mod)%mod);}
miku operator *(const miku &res){return miku((1ll*x*res.x%mod-1ll*y*res.y%mod+mod)%mod,(1ll*x*res.y%mod+1ll*y*res.x%mod-1ll*y*res.y%mod+mod)%mod);}
}f[600010],g[600010];
miku quick_pow(miku x,int y)
{
miku res=miku(1,0);
while(y)
{
if(y&1)
{
res=res*x;
}
y>>=1;
x=x*x;
}
return res;
}
void exgcd(int a,int b,int &x,int &y)
{
if(!b)
{
x=1,y=0;
}
else
{
exgcd(b,a%b,y,x);
y-=a/b*x;
}
}
int get_inv()
{
int x,y;
exgcd(n,mod,x,y);
return x=(x%mod+mod)%mod;
}
void FWT(miku *a)
{
for(int i=1;i<n;i*=3)
{
for(int l=i*3,j=0;j<n;j+=l)
{
for(int k=0;k<i;k++)
{
miku t[3]={a[j+k],a[j+k+i],a[j+k+i+i]};
a[j+k]=t[0]+t[1]+t[2];
a[j+k+i]=t[0]+t[1].s()+t[2].t();
a[j+k+i+i]=t[0]+t[1].t()+t[2].s();
}
}
}
}
void IFWT(miku *a)
{
for(int i=1;i<n;i*=3)
{
for(int l=i*3,j=0;j<n;j+=l)
{
for(int k=0;k<i;k++)
{
miku t[3]={a[j+k],a[j+k+i],a[j+k+i+i]};
a[j+k]=t[0]+t[1]+t[2];
a[j+k+i]=t[0]+t[1].t()+t[2].s();
a[j+k+i+i]=t[0]+t[1].s()+t[2].t();
}
}
}
int inv=get_inv();
for(int i=0;i<n;i++)
{
a[i].x=1ll*a[i].x*inv%mod;
}
}
int main()
{
scanf("%d%d%d",&m,&t,&mod);
n=1;
for(int i=1;i<=m;i++)
{
n*=3;
}
for(int i=0;i<n;i++)
{
scanf("%d",&f[i].x);
x[i]=x[i/3]+(i%3==1);
y[i]=y[i/3]+(i%3==2);
}
for(int i=0;i<=m;i++)
{
for(int j=0;i+j<=m;j++)
{
scanf("%d",&a[i][j]);
}
}
for(int i=0;i<n;i++)
{
g[i].x=a[x[i]][y[i]];
}
FWT(f);
FWT(g);
for(int i=0;i<n;i++)
{
f[i]=f[i]*quick_pow(g[i],t);
}
IFWT(f);
for(int i=0;i<n;i++)
{
printf("%d\n",f[i].x);
}
}
[清华集训2016]石家庄的工人阶级队伍比较坚强——三进制FWT的更多相关文章
- UOJ272 [清华集训2016] 石家庄的工人阶级队伍比较坚强 【分治乘法】
题目分析: 首先不难注意到式子就是异或卷积,所以考虑用分治乘法推出优化方法.我们把一个整体$f$拆成$f-,f\pm,f+$,然后另一个拆成$g-,g\pm,g+$.这样做的好处是能更清楚的分析问题. ...
- uoj#272. 【清华集训2016】石家庄的工人阶级队伍比较坚强
http://uoj.ac/problem/272 这题的式子形式是异或卷积的三进制推广,因此可以设计一个类似fwt的变换,这里需要一个三次单位根$w$,满足$w^3\%p==1$且$(1+w+w^2 ...
- UOJ272. 【清华集训2016】石家庄的工人阶级队伍比较坚强 [FWT]
UOJ 思路 很容易想到\(O(3^{3m}\log T)\)的暴力大矩乘,显然过不了. 我们分析一下每次转移的性质.题目给的转移方程是填表法,我们试着改成刷表法看看-- 发现好像没啥用. 注意到游戏 ...
- [uoj272]石家庄的工人阶级队伍比较坚强
假设$x,y\in \{0,1,2\}$,则$x$能赢$y$(根据题中定义)当且仅当$x-y\equiv 1(mod\ 3)$ 定义$\ominus$为两数3进制下不退位的减法,$S_{x}$表示$x ...
- UOJ #274. 【清华集训2016】温暖会指引我们前行 [lct]
#274. [清华集训2016]温暖会指引我们前行 题意比较巧妙 裸lct维护最大生成树 #include <iostream> #include <cstdio> #incl ...
- UOJ_274_[清华集训2016]温暖会指引我们前行_LCT
UOJ_274_[清华集训2016]温暖会指引我们前行_LCT 任务描述:http://uoj.ac/problem/274 本题中的字典序不同在于空串的字典序最大. 并且题中要求排序后字典序最大. ...
- UOJ 275. 【清华集训2016】组合数问题
UOJ 275. [清华集训2016]组合数问题 组合数 $C_n^m $表示的是从 \(n\) 个物品中选出 \(m\) 个物品的方案数.举个例子,从$ (1,2,3)(1,2,3)$ 三个物品中选 ...
- UOJ #269. 【清华集训2016】如何优雅地求和
UOJ #269. [清华集训2016]如何优雅地求和 题目链接 给定一个\(m\)次多项式\(f(x)\)的\(m+1\)个点值:\(f(0)\)到\(f(m)\). 然后求: \[ Q(f,n,x ...
- 【UOJ274】【清华集训2016】温暖会指引我们前行 LCT
[UOJ274][清华集训2016]温暖会指引我们前行 任务描述 虽然小R住的宿舍楼早已来了暖气,但是由于某些原因,宿舍楼中的某些窗户仍然开着(例如厕所的窗户),这就使得宿舍楼中有一些路上的温度还是很 ...
随机推荐
- 从零开始搭建react应用
用create-react-app搭建react应用,了解npm run start的工作过程. 第一步:安装脚手架 create-react-app 1. 在node里 npm install cr ...
- JavaScript使用纯函数避免bug
纯函数 一.纯函数 定义:纯函数是指不依赖并且不修改其作用域之外的函数.通过以下几个示例来认识纯函数: var a = 10; //纯函数 function foo(num){ return num ...
- vue入门:(class与style绑定)
对象语法 数组语法 一.对象语法 1.1对象语法绑定HTML Class 语法:v-bind:class="{'className1':boolean1,'className2':boole ...
- Python脚本带-的参数脚本
一.故事背景 由于先前的工作内容是做后台开发,对于脚本写的很少: 昨天参加面试遇到一道面试题,写一个python脚本: 通过脚本的后面的参数选项获取参数选项后面的字符串进行处理: 问题没记错的话大概是 ...
- ETL 工具和 BI 工具
ETL是数据仓库中的非常重要的一环,是承前启后的必要的一步.ETL负责将分布的.异构数据源中的数据如关系数据.平面数据文件等抽取到临时中间层后进行清洗.转换.集成,最后加载到数据仓库或数据集市中,成为 ...
- 由于MTU设置不当导致的访问超时
现象 工作中遇到一件怪事:搭建好服务器后(VPN服务器,创建了虚拟网卡),服务器和客户端之间响应正常且很稳定,客户端也能正常通过服务器访问外网.但是访问个别网站时可以打开文字,但是部分图片打不开(也不 ...
- Docker_云计算技术简述
Docker官方网站 > https://www.docker.com/Docker博客 > https://www.docker.com/blog/Docker内容库 > http ...
- 【转】Qt 资源图片删除后,错误 needed by `debug/qrc_image.cpp'. Stop. 的终极解决办法
@2019-06-13 [小记] Qt项目做完了把资源文件夹下已经不用的图片文件删掉,运行时报错(编译不报错):No rule to make target `images/图片文件名', neede ...
- 版本控制工具 svn 二
一.图标 忽略图标 实例 二.版本 回滚 tortoisesvn ——> 版本更新——>一般情况下使用 “显示日子” 回滚 三.版本冲突 版本冲突产生原因 多人先后提交文件,每个人提交的文 ...
- 通过SSH解压缩.tar.gz、.gz、.zip文件的方法
一般在linux下,常用的压缩格式有如下几个: .tar.gz..gz..zip 解压 .tar.gz 文件命令: tar -zxvf xxx.tar.gz 解压 .gz 文件命令: gunzip x ...