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)$ 三个物品中选 ...
随机推荐
- 跨界 - Omi 发布多端统一框架 Omip 打通小程序与 Web
Omip 今天,Omi 不仅仅可以开发桌面 Web.移动 H5,还可以直接开发小程序!直接开发小程序!直接开发小程序! Github Omi 简介 Omi 框架是微信支付线研发部研发的下一代前端框架, ...
- 朱晔的互联网架构实践心得S2E1:业务代码究竟难不难写?
注意,这是我的架构实践心得的第二季的系列文章,第一季有10篇你也可以回顾. 见https://www.cnblogs.com/lovecindywang/category/1296779.html 最 ...
- Pandas基础使用
Pandas是基于NumPy的一种工具,该工具是为了解决数据分析任务而创建的. 1.导入pandas import pandas as pd 2.pandas数据类型: 1)Series:一维数据类型 ...
- 无线网络中信噪比(SNR)计算
信噪比(S/N)=log[信号功率密度/噪声功率密度] a =log[信号功率密度]-log[噪声功率密度] 例如,接收端的信号功率密度为-63dBm,噪声的信号功率密度为-95dBm,则: 信噪比( ...
- 杭电 1061 Rightmost Digit计算N^N次方的最后一位
Problem Description Given a positive integer N, you should output the most right digit of N^N. Input ...
- 未能加载文件或程序集"Newtonsoft.Json, Version=4.5.0.0
这问题遇到好几次了,重新更改了引用都不好使,有的时候版本改成一致就好了,但是有的地方你不知道在哪里用了就不好排查,所性在config里面加个配置让程序运行的时候去处理得了~ 很实用,放在configu ...
- Redis缓存用起来
Redis缓存用起来 1. 引言 创建任务时我们需要指定分配给谁,Demo中我们使用一个下拉列表用来显示当前系统的所有用户,以供用户选择.我们每创建一个任务时都要去数据库取一次用户列表,然后绑定到用户 ...
- Python+Appium学习篇之WebView处理
1.认识WebView 实例说明: 当你打开百度阅读APP→VIP全站去广告→用自带的 UI Automator去定位里面的元素,如图: 不管你去定位 '规则详情' '开通'等等,都会定位不到,只 ...
- sqlserver笔记
表结构: 一,字段类型sqlserver jdbc java char char Stringnchar nchar Stringvarchar varchar Stringnvarchar nvar ...
- 学习 yii2.0——视图之间相互包含
布局 首先创建一个布局文件simple.php,路径是在views/layout/目录下. <p>this is header</p> <?= $content ?> ...