[UOJ500]任意基DFT
题目
传送门 to UOJ
思路
多点求值是 O(qlog2n)\mathcal O(q\log^2 n)O(qlog2n) 的,无法通过。要利用点值的特殊性。题面里声称是因为 “输入量较大”,放屁嘞!
设 qn=xqn−1+y(n∈N+)q_n=xq_{n-1}+y\;(n\in\N^+)qn=xqn−1+y(n∈N+),很容易求出通项公式
qn=xn−1x−1⋅y+xnq0q_n={x^n-1\over x-1}\cdot y+x^nq_0 qn=x−1xn−1⋅y+xnq0
注意到变量只有 xnx^nxn,所以把它简化为 kxn+bkx^n+bkxn+b 。具体值就自己对应一下就好了。
这时候我们会想要将这个值直接代入,来观察式子的性质。设 f(x)=∑aixif(x)=\sum a_ix^if(x)=∑aixi,则
f(kxm+b)=∑i,jai(ij)⋅kjxmjbi−j=∑jxmj⋅kjj!∑i(i!⋅ai)⋅bi−j(i−j)!f(kx^m+b)=\sum_{i,j}a_i{i\choose j}\cdot k^jx^{mj}b^{i-j}\\ =\sum_{j}x^{mj}\cdot{k^j\over j!}\sum_{i}(i!\cdot a_i)\cdot{b^{i-j}\over(i-j)!} f(kxm+b)=i,j∑ai(ji)⋅kjxmjbi−j=j∑xmj⋅j!kji∑(i!⋅ai)⋅(i−j)!bi−j
注意到 xmjx^{mj}xmj 说白了就是 (xm)j(x^m)^j(xm)j,而右侧又是只与 jjj 有关的系数,所以我们会考虑直接求出系数 vj=kjj!∑i(i!⋅ai)⋅bi−j(i−j)!v_j=\frac{k^j}{j!}\sum_{i}(i!\cdot a_i)\cdot{b^{i-j}\over(i-j)!}vj=j!kj∑i(i!⋅ai)⋅(i−j)!bi−j,显然这是 O(nlogn)\mathcal O(n\log n)O(nlogn) 一次卷积就可以完成的。记 g(x)=∑jvjxjg(x)=\sum_{j}v_jx^jg(x)=∑jvjxj,接下来只需求出 g(xm)g(x^m)g(xm) 。
利用这里讲的 Bluestain\text{Bluestain}Bluestain 算法,用 mj=(m+j2)−(m2)−(j2)mj={m+j\choose 2}-{m\choose 2}-{j\choose 2}mj=(2m+j)−(2m)−(2j) 就可凑出卷积形式。时间复杂度 O[(n+q)log(n+q)]\mathcal O[(n+q)\log(n+q)]O[(n+q)log(n+q)] 。
代码
#include <cstdio> // Dangerous Dark Ghost!!!
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cctype>
using namespace std;
# define rep(i,a,b) for(int i=(a); i<=(b); ++i)
# define drep(i,a,b) for(int i=(a); i>=(b); --i)
typedef long long llong;
inline int readint(){int a = 0, c = getchar(), f = 1;for(; !isdigit(c); c=getchar())if(c == '-') f = -f;for(; isdigit(c); c=getchar())a = (a<<3)+(a<<1)+(c^48);return a*f;
}
void writeint(unsigned x){if(x > 9) writeint(x/10);putchar(char((x%10)^48));
}const int MOD = 998244353, LOGMOD = 30;
inline int modAdd(int a,int b){return (a += b) >= MOD ? (a -= MOD) : a;
}
inline void modAddUp(int &a,int b){if((a += b) >= MOD) a -= MOD;
}
inline int qkpow(llong b,int q){llong a = 1;for(; q; q>>=1,b=b*b%MOD)if(q&1) a = a*b%MOD;return static_cast<int>(a);
}int g[LOGMOD], inv2[LOGMOD];
void prepare(){int p = MOD-1, x = 0; inv2[0] = 1;for(inv2[1]=(MOD+1)>>1; !(p&1); p>>=1,++x)inv2[x+1] = int(llong(inv2[x])*inv2[1]%MOD);for(g[x]=qkpow(3,p); x; --x)g[x-1] = int(llong(g[x])*g[x]%MOD);
}const int MAXN = 3000005;
void NTT(int a[],int n){const int *end_a = a+(1<<n);for(int w=1<<n>>1,x=n; w; w>>=1,--x)for(int *p=a; p!=end_a; p+=(w<<1))for(int i=0,v=1; i!=w; ++i){const llong l = p[i];modAddUp(p[i],p[i+w]);p[i+w] = int(llong(l+MOD-p[i+w])*v%MOD);v = int(llong(v)*g[x]%MOD);}
}
void DNTT(int a[],int n){const int *end_a = a+(1<<n);for(int w=1,x=1; x<=n; w<<=1,++x)for(int *p=a; p!=end_a; p+=(w<<1))for(int i=0,v=1; i!=w; ++i){const int t = int(llong(p[i+w])*v%MOD);p[i+w] = modAdd(p[i],MOD-t);modAddUp(p[i],t); // ordinaryv = int(llong(v)*g[x]%MOD);}std::reverse(a+1,a+(1<<n));for(int *i=a; i!=end_a; ++i)*i = int(llong(*i)*inv2[n]%MOD);
}int a[MAXN], tmp[MAXN], inv[MAXN];
int main(){prepare(); // DON'T FORGET THIS!int n = readint(), q = readint();rep(i,(inv[1]=1)+1,n)inv[i] = int(llong(MOD-MOD/i)*inv[MOD%i]%MOD);rep(i,0,n) a[i] = readint();int g0 = readint();int gx = readint(), gy = readint();int b = int(llong(gy)*qkpow(gx-1,MOD-2)%MOD);int k = b+g0; if(b) b = MOD-b;int N = 1; for(; (1<<N)<=(n<<1); ++N);for(int i=0,jc=1; i<=n; ++i){a[i] = int(llong(jc)*a[i]%MOD);jc = int(llong(jc)*(i+1)%MOD); // i!}for(int i=n-(tmp[n]=1); ~i; --i)tmp[i] = int(llong(tmp[i+1])*inv[n-i]%MOD*b%MOD);NTT(a,N), NTT(tmp,N); // mother f**ker polymulfor(int i=0; i!=(1<<N); ++i)a[i] = int(llong(a[i])*tmp[i]%MOD);DNTT(a,N); memmove(a,a+n,(n+1)<<2); // memmovefor(; (1<<N)<=(n<<1)+q; ++N); // biggerconst int invgx = qkpow(gx,MOD-2);for(int i=0,v=1,av=1,avv=1; i<=n; ++i){a[i] = int(llong(v)*a[i]%MOD*avv%MOD);v = int(llong(v)*inv[i+1]%MOD*k%MOD);avv = int(llong(avv)*av%MOD); // x^{-i*(i-1)/2}av = int(llong(av)*invgx%MOD); // x^{-i}}std::reverse(a,a+n+1); // reversememset(a+n+1,0,((1<<N)-n-1)<<2);for(int i=0,v=1,av=1; i<=n+q; ++i){tmp[i] = av; // x^{i*(i-1)/2}av = int(llong(av)*v%MOD);v = int(llong(v)*gx%MOD);}memset(tmp+n+q+1,0,((1<<N)-q-n-1)<<2);NTT(a,N), NTT(tmp,N);for(int i=0; i!=(1<<N); ++i)a[i] = int(llong(a[i])*tmp[i]%MOD);DNTT(a,N); memmove(a,a+n,(q+1)<<2);for(int i=0,v=1,av=1; i<=q; ++i){a[i] = int(llong(a[i])*av%MOD);av = int(llong(av)*v%MOD);v = int(llong(v)*invgx%MOD);}int xyx = 0; // xor sumfor(int i=1; i<=q; ++i)xyx ^= a[i]; // answerprintf("%d\n",xyx);return 0;
}
[UOJ500]任意基DFT相关推荐
- CheatMaker教学进阶之一 - 基地址与指针
CheatMaker目前还是有一些需要完善的地方 最大的一个缺点是无法用控件直接使用指针寻址的方法写地址 不过软件作者表示这个将在CheatMaker 1.70时解决 但是本文的主旨是来说明Cheat ...
- GCN—图卷积神经网络理解
文章目录 一.CNN卷积 二.GCN 图卷积神经网络 2.1 GCN优点 2.3 提取拓扑图空间特征的两种方式 三.拉普拉斯矩阵 3.1 拉普拉斯矩阵的谱分解(特征分解) 3.2 傅里叶变换.卷积类比 ...
- 快速傅里叶变换简明教程与实现
目录 开场白 基础数学 1.复数运算 2.欧拉公式 基础信号论 奈奎斯特采样定理 从解方程到傅里叶变换 1.何方神圣 2.分量求解:从方程开始 3.得到DFT(可读) 快速傅里叶变换的原理与细节 1. ...
- 【转】C++的面象对象总结
转自:http://www.cnblogs.com/icemoon1987/archive/2012/10/01/2709572.html 1. 面向对象:对象.类.继承 2. 构造函数: 类的数据成 ...
- Generalized Linear Models
作者:桂. 时间:2017-05-22 15:28:43 链接:http://www.cnblogs.com/xingshansi/p/6890048.html 前言 主要记录python工具包:s ...
- C++知识点52——多重继承
一.概念 C++允许一个类拥有多个基类,所以就有了多重继承.多重继承和单一继承很多方面都是类似的. 示例 class zooanimal { public:zooanimal(){cout<&l ...
- gj4 深入类和对象
4.1 鸭子类型和多态 当看到一只鸟走起来像鸭子.游永起来像鸭子.叫起来也像鸭子,那么这只鸟就可以被称为鸭子 只要利用Python的魔法函数,就能实现某些Python数据类型的类似的方法. class ...
- JavaScript常见面试题和答案
原文地址:https://www.yisu.com/zixun/117910.html 这篇文章将为大家详细讲解有关JavaScript常见面试题和答案,小编觉得挺实用的,因此分享给大家做个参考,希望 ...
- Python深入类和对象
一. 鸭子类型和多态 1.什么是鸭子类型: 在程序设计中,鸭子类型(英语:Duck typing)是动态类型和某些静态语言的一种对象推断风格."鸭子类型"像多态一样工作,但是没有继 ...
最新文章
- 修改PostgreSQL数据库默认用户postgres的密码
- CH - 6802 車的放置(二分图最大匹配)
- linux-redhat替换yum网络源为centos网络源
- [Linux主机] 优化你的php-fpm(php5.3+)让你的网站跑得更快
- Windows下安装scikit-learn
- 基于物联网的工业分析将席卷制造业
- 数学魔鬼表达式——第一天
- it人才外包公司招人真的很难吗?
- 基于SNMP数据采集模块的设计和实现2
- linux命令练习题
- pyspark 数据框 更改大小写_英文字母大小写
- 关于在Unity2018中使用Vuforia实现基础图片识别AR展现效果
- 哪些学校有计算机博士点,哪些学校有计算机应用博士点
- Chrome 浏览器 模糊的解决方法
- 跑步时你最关心配速吗,真正会跑步的人更看重这个
- ionic3生产打包javascript内存溢出的解决方法
- Python爬虫教程:微医挂号网医生数据抓取
- 计蒜客习题:骑车比赛
- Nginx-初识Nginx-第二天
- 卖桃子问题(递归函数求解)
热门文章
- 学术-物理-维空间:四维空间(标准欧几里得空间)
- 树莓派Ubuntu 20.04网络设置
- org.postgresql.util.PSQLException: 不良的类型值 long : \x
- Windows下如何查看sqlite数据库
- 第一次日志大二下11周2019.5.12
- CONVERT()函数
- Conan教程(2)—— 安装
- The Travelling Customer (Coding, Training)
- 移动通信下的语音业务
- 2007-2008期末试题A卷