[codeforces 901E] Cyclic Cipher 循环卷积-Bluestein's Algorithm
题目大意:
给两个数列${B_i}、{C_i}$,长度均为$n$,且${B_i}$循环移位线性无关,即不存在一组系数${X_i}$使得对于所有的$k$均有$\sum_{i=0}^{n-1} X_i B_{k-i \mod n} =0$。
已知$C$是由$B$与$A$构造得到:
(搬原图)。
求所有合法的$A$序列。
题解:
首先把式子稍加化简会得到:
显然是个差分式,然后就会得到以下两种结果(以下$B_{i}$均为$B_{i\mod n}$):

问题是,这两个式子都是对的吗?
显然不是。
我们考虑题目中说的${B_i}$为循环移位线性无关,但是$\Delta B_i=B_{i+1}-B_{i}$构成的${\Delta B_{i}}$我们是不知道它是否是线性无关的,如果是线性无关,那么它是正确的,反之,我们会知道必然存在一组${X_i}$使得若${A}$有解,则有无穷解,但是回带是错误的。
但是二式我们如果可以求解可知$\Delta A_i=A_{i+1}-A{i}$是有唯一解的,然后考虑回带求$A_0$我们就可以得到最多两个解。
所以本题就变成了求:
设$B'_i=B_{-i}$,即:

即,问题变为求出$\Delta C$的点值然后除去$B'_{*Z/n}$的点值再除去$-2$我们再由$\Delta A$的点值求出其系数即可。
当然,我们可以知道$\Delta A$的系数小于$2e3$,所以我们防止卡精使用$NTT$。
由于并不知道$B'_{*Z/n}$的长度,所以不能裸上,需要使用Bluestein's Algorithm。
这个东西网上几乎没有讲解,好像毛爷爷的《再探》里面有说?
具体就是:

这样就可以使用一次卷积来求$B'$的点值了。($NTT$并不能直接拆成上面的形式,因为数论变换是没法消去下面除的那个2)
所以将$ik$变为
然后拆解即可。
代码:
#include "bits/stdc++.h"
typedef long long ll;
inline int read() {
int s=,k=;char ch=getchar();
while (ch<''|ch>'') ch=='-'?k=-:,ch=getchar();
while (ch>&ch<='') s=s*+(ch^),ch=getchar();
return s*k;
}
const int N=6e5+;
ll mod,g,w[][N],W[][N];
inline ll Mult ( ll a,ll b ) {
return ( a*b - (ll)( (long double) a*b/mod )*mod + mod )% mod;
}
inline ll powmod ( ll a, ll b ) {
ll ret=;
while (b) {
if (b&) ret=Mult ( ret, a );
b>>=,a=Mult ( a, a);
}return ret;
}
inline ll gcd ( ll a,ll b ) { return b?gcd(b,a%b) : a; }
int n,m;
inline void Get_mod () {
for (m=; (m<=*n) ;m<<= );
ll lcm =1ll* n*m /gcd (n,m);
mod = lcm + ;
while ( mod < 1e5 ) mod += lcm;
while () {
int flag=true;
for (int i=;1ll*i*i<=mod;++i) if (mod%i==) {flag=false;break;}
if (flag) break;
mod+=lcm;
}
for (g=;;++g) {
int flag=true;
for (int i=;1ll*i*i<=mod;++i) if ((mod-)%i==){
if (powmod(g,i)==) {flag=false;break;}
if (powmod(g,(mod-)/i)==) {flag=false;break;}
}
if (flag) break;
}
}
inline void Get_wn(){
ll w0=powmod(g,(mod-)/m);
w[][]=w[][]=;
int i;
for (i=;i<m;++i) w[][i]=Mult(w[][i-],w0);
for (i=;i<m;++i) w[][i]=w[][m-i];
w0=powmod(g,(mod-)/n);
W[][]=W[][]=;
for (i=;i<n;++i) W[][i]=Mult(W[][i-],w0);
for (i=;i<n;++i) W[][i]=W[][n-i];
}
inline void NTT(ll *a,int n,int f) {
register int i,j,k,l,t;
for (i=j=;i^n;++i) {
if (i>j) std::swap(a[i],a[j]);
for (k=n>>;(j^=k)<k;k>>=);
}
for (i=;i<n;i<<=)
for (j=,t=n/(i<<);j<n;j+=i<<)
for (k=l=;k<i;++k , l+=t ) {
ll x=a[j+k],y=Mult(a[i+j+k],w[f][l]);
a[j+k]=x+y;
a[i+j+k]=x-y;
if (a[j+k]>=mod) a[j+k]-=mod;
if (a[i+j+k]<) a[i+j+k]+=mod;
}
if (f ) {
ll rev=powmod ( n,mod- );
for (i=;i<n;++i) a[i]=Mult(a[i],rev);
}
}
ll Y[N];
inline void pre_Bluestein(int f) {
int i;
for (i=;i<*n;++i) Y[*n--i]=W[f][1ll*i*(i-)/%n];
for (i=*n;i<m;++i) Y[i]=;
NTT(Y,m,);
}
inline void Bluestein(ll *a,int f){
static ll X[N];
register int i;
for (i=;i<n;++i) X[i]=Mult(a[i],W[f][ (n-1ll*i*(i-)/%n)%n ]);
for (i=n;i<m;++i) X[i]=;
NTT(X,m,);
for (i=;i<m;++i) X[i]=Mult(X[i],Y[i]);
NTT(X,m,);
for (i=;i<n;++i)
a[i]=Mult (X[*n--i],W[f][(n-1ll*i*(i-)/%n)%n ]);
if (f) {
ll rev=powmod(n,mod-);
for (i=;i<n;++i) a[i]=Mult(a[i],rev);
}
}
int b[N],c[N];
ll rev_b[N],delta_c[N],delta_a[N],a[N];
int main() {
//freopen(".in","r",stdin);
n = read();
register int i;
for (i=;i<n;++i) b[i]=read();
for (i=;i<n;++i) c[i]=read();
Get_mod();
Get_wn();
for (i=;i<n;++i) rev_b[i]=b[i];
std::reverse(rev_b+,rev_b+n);
ll inv_2=powmod(mod-,mod-);
for (i=;i<n;++i) delta_c[i]=Mult ( ( c[(i+)%n]-c[i] + mod )%mod , inv_2 );
pre_Bluestein();
Bluestein(rev_b,);
Bluestein(delta_c,);
for (i=;i<n;++i) delta_a[i]=Mult ( delta_c[i] , powmod (rev_b[i],mod-) );
pre_Bluestein();
Bluestein(delta_a,);
for (i=;i<n;++i) {
ll v=(delta_a[i]<mod-delta_a[i])?delta_a[i]:delta_a[i]-mod;
if (abs(v)>) return puts(""),;
a[i]=v;
}
ll _c=-c[],_a=,_b=,sum=;
for (i=;i<n;++i) {
++_a;
_b+=*(sum-b[i]);
_c+=(sum-b[i])*(sum-b[i]);
sum+=a[i];
}
if (sum!=) {
puts("");
return ;
}
std::set<ll> ans;
if (_b*_b-*_a*_c>=){
ll s=ll(sqrt(_b*_b-*_a*_c) + 0.5);
if (s*s!=_b*_b-*_a*_c) return puts(""),;
if ((-_b+s)%(*_a)==) ans.insert((-_b+s)/(*_a));
if ((-_b-s)%(*_a)==) ans.insert((-_b-s)/(*_a));
}
std::set<ll>::iterator it;
printf("%d\n",ans.size());
for (it=ans.begin();it!=ans.end();++it) {
ll now=*it;
for (i=;i<n;++i){
printf("%lld ",now);
now+=a[i];
}
puts("");
}
}
codeforces901E
[codeforces 901E] Cyclic Cipher 循环卷积-Bluestein's Algorithm的更多相关文章
- codeforces 722F - Cyclic Cipher
题目链接:http://codeforces.com/problemset/problem/722/F ------------------------------------------------ ...
- Bluestein's Algorithm
网上很少有人提到,写的也很简单,事实上就是很简单... \(Bluestein's\ Algorithm\),用以解决任意长度\(DFT\). 考虑\(DFT\)的形式:\[\begin{aligne ...
- CodeForces - 156C:Cipher (不错的DP)
Sherlock Holmes found a mysterious correspondence of two VIPs and made up his mind to read it. But t ...
- Codeforces - 102222C - Caesar Cipher
https://codeforc.es/gym/102222/my 好像在哪里见过这个东西?字符的左右移还是小心,注意在mod26范围内. #include<bits/stdc++.h> ...
- codeforces 708ALetter Cyclic Shift
2019-05-18 09:51:19 加油,加油,fightting !!! https://www.cnblogs.com/ECJTUACM-873284962/p/6375011.html 全为 ...
- 再探快速傅里叶变换(FFT)学习笔记(其三)(循环卷积的Bluestein算法+分治FFT+FFT的优化+任意模数NTT)
再探快速傅里叶变换(FFT)学习笔记(其三)(循环卷积的Bluestein算法+分治FFT+FFT的优化+任意模数NTT) 目录 再探快速傅里叶变换(FFT)学习笔记(其三)(循环卷积的Blueste ...
- Codeforces Round #453 (Div. 1)
Codeforces Round #453 (Div. 1) A. Hashing Trees 题目描述:给出一棵树的高度和每一层的节点数,问是否有两棵树都满足这个条件,若有,则输出这两棵树,否则输出 ...
- Codeforces Round #453
Visiting a Friend Solution Coloring a Tree 自顶向下 Solution Hashing Trees 连续2层节点数都超过1时能异构 Solution GCD ...
- 【Codeforces 1083C】Max Mex(线段树 & LCA)
Description 给定一颗 \(n\) 个顶点的树,顶点 \(i\) 有点权 \(p_i\).其中 \(p_1,p_2,\cdots, p_n\) 为一个 \(0\sim (n-1)\) 的一个 ...
随机推荐
- MongoDB学习笔记(二)
一.Mongodb命令 说明:Mongodb命令是区分大小写的,使用的命名规则是驼峰命名法. 对于database和collection无需主动创建,在插入数据时,如果database和collect ...
- [Domino]Java访问Domino必需配置的服务器设置
应用场景 我们需要通过Java远程访问IBM Lotus Domino R6和R5服务器,从中获取用户邮箱的邮件信息等关键数据.我们不需要提供每一个用户密码以及ID文件. 我们的具体做法是,通过Dom ...
- VueJs(9)---组件(父子通讯)
组件(父子通讯) 一.概括 在一个组件内定义另一个组件,称之为父子组件. 但是要注意的是:1.子组件只能在父组件内部使用(写在父组件tempalte中); 2.默认情况下,子组件无法访问父组件上的数据 ...
- 装修工人如何在网上"找活"
http://blog.sina.com.cn/s/blog_555e8fe80102wwsz.html ps:其实码农也是一种装修工. 在这个互联网时代,各个行业都在利用网络达到自己的商业目的,作为 ...
- Android 众多的布局属性详解
http://www.open-open.com/lib/view/open1328686184311.html Android功能强大,界面华丽,但是众多的布局属性就害苦了开发者,下面这篇文章结合了 ...
- unity做游戏常用功能实现(一)多方向同时输入也能让物体正常移动
-------小基原创,转载请给我一个面子 网上有很多讲输入控制如何移动,但是多数都是讲单一按下,对于同时按下2个或2个以上按键并没有说明怎么解决,这里小基研究了一下方便大家 (如果你直接写input ...
- error LNK2038: 检测到“RuntimeLibrary”的不匹配项: 值“MTd_StaticDebug”不匹配值“MDd_DynamicDebug
属性1. 在工程上右键->属性->c/c++->代码生成->运行库 四个选项及含义分别如下: 1.1 /MDd:MD_DynamicDebug,我理解是 "共享DLL ...
- Python杂记
一.函数 1.numpy 模块中的nonzero函数 nonzero返回的数非零元素的下标. 如果输入是单维度的时候它的返回值只有一个:如果输入是多个维度的话,那么它的返回值也是多个维度的.并且的它的 ...
- 如何更好的编写async函数
2018年已经到了5月份,node的4.x版本也已经停止了维护 我司的某个服务也已经切到了8.x,目前正在做koa2.x的迁移 将之前的generator全部替换为async 但是,在替换的过程中,发 ...
- TCP连接的建立与释放(三次握手与四次挥手)
TCP连接的建立与释放(三次握手与四次挥手) TCP是面向连接的运输层协议,它提供可靠交付的.全双工的.面向字节流的点对点服务.HTTP协议便是基于TCP协议实现的.(虽然作为应用层协议,HTTP协议 ...