UOJ272 [清华集训2016] 石家庄的工人阶级队伍比较坚强 【分治乘法】
题目分析:
首先不难注意到式子就是异或卷积,所以考虑用分治乘法推出优化方法。
我们把一个整体$f$拆成$f-,f\pm,f+$,然后另一个拆成$g-,g\pm,g+$.这样做的好处是能更清楚的分析问题。下面我们下宽油(大雾)。
发现三个部分要求的式子是在两者相乘中选不同的三个,所以我们发现三个部分中每取一个有相同。这样我们聚焦到$--,-\pm,-+$三个东西。观察二进制FWT,可以假想它们要使用到三次单位根。这样只需要把三个根错开排列就行了。
做分治乘法的时候注意把虚部的$I$记做$\sqrt{3}i$.
代码:
#include<bits/stdc++.h>
using namespace std; const int maxn = ; struct cn{int rl,vir;}e[]; // vir's real meaning is vir*sqrt(3) int iv2,iv3;
int m,n,t,p,phi;
int b3[],b[][];
cn val[maxn],f[maxn]; int W[maxn],L[maxn]; cn operator +(const cn& alpha,const cn& beta){
cn ans = (cn){alpha.rl+beta.rl,alpha.vir+beta.vir};
if(ans.rl >= p) ans.rl -= p;
if(ans.vir >= p) ans.vir -= p;
return ans;
}
cn operator *(const cn& alpha,const cn& beta){
cn ans = (cn){,};
ans.rl = (1ll*alpha.rl*beta.rl-3ll*alpha.vir*beta.vir)%p;
ans.rl += p; if(ans.rl >= p) ans.rl -= p;
ans.vir = (1ll*alpha.vir*beta.rl+1ll*alpha.rl*beta.vir)%p;
return ans;
}
cn operator *(const cn& alpha,const int& beta){
cn ans=alpha;ans.rl=(1ll*ans.rl*beta)%p;ans.vir=(1ll*ans.vir*beta)%p;
return ans;
} cn fast_pow(cn now,int pw){
int bit = ;cn ans = (cn){,},dt = now;
while(bit <= pw){
if(bit & pw) ans = ans*dt;
bit<<=;dt = dt*dt;
}
return ans;
}
int fast_pow(int now,int pw){
int bit = ,ans = ,dt = now;
while(bit <= pw){
if(bit & pw) ans = (1ll*ans*dt)%p;
bit<<=;dt = (1ll*dt*dt)%p;
}
return ans;
} void read(){
scanf("%d%d%d",&m,&t,&p);
b3[] = ; for(int i=;i<=m;i++) b3[i] = b3[i-]*;
n = b3[m];
for(int i=;i<n;i++) scanf("%d",&f[i].rl);
for(int i=;i<=m;i++){
for(int j=;i+j<=m;j++){
scanf("%d",&b[i][j]);
}
}
val[].rl = b[][];
for(int i=;i<n;i++){
W[i] = W[i/],L[i] = L[i/];
if(i % == ) L[i]++;
if(i % == ) W[i]++;
val[i].rl = b[W[i]][L[i]];
}
} void multi(int l,int r){
if(l == r-){
f[l] = f[l]*fast_pow(val[l],t);
}else{
int l1 = l+(r-l)/,l2 = l+*(r-l)/,d = l2-l1;
for(int i=;i<d;i++){
cn p1 = f[l+i],p2 = f[l1+i],p3 = f[l2+i];
f[l+i] = p1+p2+p3;
f[l1+i] = p1+e[]*p2+e[]*p3;f[l2+i] = p1+e[]*p2+e[]*p3;
p1 = val[l+i],p2 = val[l1+i],p3 = val[l2+i];
val[l+i] = p1+p2+p3;
val[l1+i] = p1+e[]*p2+e[]*p3;val[l2+i] = p1+e[]*p2+e[]*p3;
}
multi(l,l1); multi(l1,l2); multi(l2,r);
for(int i=;i<d;i++){
cn p1 = f[l+i],p2 = f[l1+i],p3 = f[l2+i];
f[l+i] = p1+p2+p3;
f[l1+i] = p1+e[]*p2+e[]*p3;f[l2+i] = p1+e[]*p2+e[]*p3;
f[l+i]=f[l+i]*iv3;f[l1+i]=f[l1+i]*iv3;f[l2+i]=f[l2+i]*iv3;
}
}
} void init(){
phi = p;int z = p;
for(int i=;i*i<=p;i++){
if(p % i == ){
while(p%i == ) p /= i;
phi = (phi/i)*(i-);
}
}
if(p != ) phi = (phi/p)*(p-); p =z;
iv2 = fast_pow(,phi-); iv3 = fast_pow(,phi-);
e[] = (cn){,}; e[] = (cn){p-iv2,iv2}; e[] = (cn){p-iv2,p-iv2};
} void work(){
multi(,n);//[0,n)
for(int i=;i<n;i++) printf("%d\n",f[i].rl);
} int main(){
read();
init();
work();
return ;
}
UOJ272 [清华集训2016] 石家庄的工人阶级队伍比较坚强 【分治乘法】的更多相关文章
- [清华集训2016]石家庄的工人阶级队伍比较坚强——三进制FWT
题目链接: [清华集训2016]石家庄的工人阶级队伍比较坚强 题目大意:有$n=3^m$个人玩石头剪刀布,共$t$轮游戏,每轮每个人要和包括自己的所有人各进行$m$次石头剪刀布.每个人在$m$轮中的决 ...
- 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 ...
- [uoj272]石家庄的工人阶级队伍比较坚强
假设$x,y\in \{0,1,2\}$,则$x$能赢$y$(根据题中定义)当且仅当$x-y\equiv 1(mod\ 3)$ 定义$\ominus$为两数3进制下不退位的减法,$S_{x}$表示$x ...
- uoj#276. 【清华集训2016】汽水(分数规划+点分治)
传送门 没想到点分治那一层-- 首先不难发现这是个分数规划,先把所有的边长减去\(k\),二分答案,设为\(mid\),就是要求路径平均值\(ans\in[-mid,mid]\) 先来考虑\(ans\ ...
- 【UOJ276】【清华集训2016】汽水(分数规划+点分治)
点此看题面 大致题意: 给你一棵树,要求你选择一条树上路径,使得这条路径上边权的平均值与定值\(k\)的差的绝对值最小.求出这个最小值. 分数规划 看到平均值,首先就应该想到分数规划吧. 我们二分答案 ...
- 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)$ 三个物品中选 ...
随机推荐
- 朱晔和你聊Spring系列S1E3:Spring咖啡罐里的豆子
标题中的咖啡罐指的是Spring容器,容器里装的当然就是被称作Bean的豆子.本文我们会以一个最基本的例子来熟悉Spring的容器管理和扩展点. 阅读PDF版本 为什么要让容器来管理对象? 首先我们来 ...
- 跨语言调用Hangfire定时作业服务
跨语言调用Hangfire定时作业服务 背景 Hangfire允许您以非常简单但可靠的方式执行后台定时任务的工作.内置对任务的可视化操作.非常方便. 但令人遗憾的是普遍都是业务代码和hagnfire服 ...
- Django Rest framework基础使用之View:APIView, mixins, generic, viewsets
先看一张图,对DRF的各个APIView,Mixin,Viewset等有个基本印象: 具体使用方法: 1.APIView: DRF 的API视图 有两种实现方式: 一种是基于函数的:@api_view ...
- github/gitlab同时管理多个ssh key
之前一直用github,但是github有一个不好的地方,要是创建私有的项目的话需要付费,而gitlab上则可以免费创建管理私有的项目.由于最近想把自己论文的一些东西整理一下,很多东西还是不方便公开, ...
- CF每日一练 Codeforces Round #520 (Div. 2)
比赛过程总结:过程中有事就玩手机了,后面打的状态不是很好,A题理解错题意,表明了内心不在状态,B题想法和思路都是完全正确的,但是并没有写出来,因为自己代码能力不强,思路不是特别清晰,把代码后面写乱了, ...
- webpack之loader和plugin简介
webpack之loader和plugin简介 webpack入门和实战(二):全面理解和运用loader和plugins webpack入门(四)——webpack loader 和plugin w ...
- main函数如何调用文件外的函数
- C#跨进程读取listview控件中的数据
http://www.cnblogs.com/Charltsing/p/slv32.html 欢迎交流:QQ564955427 读取标准的32位listview控件中的数据,网上已经有很多代码了.今天 ...
- p141一致有界原则
1.Mk取sup 为什么只要取∩就好了 不应该是先并后交吗 2.为什么说是闭集?
- 使用PHPExcel导出数据库表结构及内容
导出表结构: mysql> desc user ; +----------+--------------+------+-----+---------------------+--------- ...