牛顿迭代,多项式求逆,除法,开方,exp,ln,求幂
牛顿迭代
若
\]
牛顿迭代
\]
以下多数都可以牛顿迭代公式一步得到
多项式求逆
给定\(A(x)\)求满足\(A(x)*B(x)=1\)的\(B(x)\)
写成
\]
我们会求$$A(x)*B(x)=1(mod \ x^1)$$
然后我们考虑求$$A(x)*B(x)=1(mod \ x^t)$$
\]
\]
把\(2B(x)-A(x)*B^2(x)\)当作新的\(B\)倍增算
从\(mod \ x^1\)倍增到大于等于\(n\)
# include <bits/stdc++.h>
# define RG register
# define IL inline
# define Fill(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long ll;
const int _(4e5 + 5);
const int Zsy(998244353);
const int Phi(998244352);
const int G(3);
IL int Input(){
RG int x = 0, z = 1; RG char c = getchar();
for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
return x * z;
}
IL int Pow(RG ll x, RG ll y){
RG ll ret = 1;
for(; y; x = x * x % Zsy, y >>= 1)
if(y & 1) ret = ret * x % Zsy;
return ret;
}
int N, r[_], l, A[_], B[_];
IL void NTT(RG int *P, RG int opt){
for(RG int i = 0; i < N; ++i) if(i < r[i]) swap(P[i], P[r[i]]);
for(RG int i = 1; i < N; i <<= 1){
RG int wn = Pow(G, Phi / (i << 1));
if(opt == -1) wn = Pow(wn, Zsy - 2);
for(RG int j = 0, p = i << 1; j < N; j += p)
for(RG int w = 1, k = 0; k < i; w = 1LL * w * wn % Zsy, ++k){
RG int X = P[k + j], Y = 1LL * w * P[k + j + i] % Zsy;
P[k + j] = (X + Y) % Zsy, P[k + j + i] = (X - Y + Zsy) % Zsy;
}
}
}
IL void Mul(RG int *a, RG int *b, RG int len){
for(l = 0, N = 1, len += len - 1; N <= len; N <<= 1) ++l;
for(RG int i = 0; i < N; ++i) r[i] = (r[i >> 1] >> 1) | ((i & 1) << (l - 1));
for(RG int i = 0; i < N; ++i) A[i] = B[i] = 0;
for(RG int i = 0; i <= len >> 1; ++i) A[i] = a[i], B[i] = b[i];
NTT(A, 1), NTT(B, 1);
for(RG int i = 0; i < N; ++i) A[i] = 1LL * A[i] * B[i] % Zsy * B[i] % Zsy;
NTT(A, -1);
RG int inv = Pow(N, Zsy - 2);
for(RG int i = 0; i <= len; ++i) A[i] = 1LL * A[i] * inv % Zsy;
}
int n, a[_], b[_], c[_], m;
int main(RG int argc, RG char *argv[]){
n = Input();
for(RG int i = 0; i < n; ++i) a[i] = Input() % Zsy;
for(m = 1; m < n; m <<= 1);
b[0] = Pow(a[0], Zsy - 2);
for(RG int t = 2; t <= m; t <<= 1){
for(RG int i = 0; i < t; ++i) c[i] = b[i];
Mul(a, b, t);
for(RG int i = 0; i < t; ++i)
b[i] = ((c[i] + c[i]) % Zsy - A[i] + Zsy) % Zsy;
}
for(RG int i = 0; i < n; ++i) printf("%d ", b[i]);
return puts(""), 0;
}
多项式除法
已知\(n\)次多项式\(A(x)\)和\(m\)次多项式\(B(x)\),\(n>m\)
求\(A(x)\)除以\(B(x)\)的商\(C(x)\)及余式\(D(x)\)
也就是
\]
\]
\]
对\(x^{n-m+1}\)取模
\]
\(R\)表示把系数倒置,即\(swap\)前后
那么可以多项式求逆,再相乘得到\(C^R(x)\)
然后去掉\(R\)带入原式相乘再相减得到\(D(x)\)
# include <bits/stdc++.h>
# define IL inline
# define RG register
# define Fill(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long ll;
IL int Input(){
RG int x = 0, z = 1; RG char c = getchar();
for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
return x * z;
}
const int mod(998244353);
const int phi(998244352);
const int maxn(8e5 + 5);
const int g(3);
IL int Pow(RG ll x, RG ll y){
RG ll ret = 1;
for(; y; y >>= 1, x = x * x % mod)
if(y & 1) ret = ret * x % mod;
return ret;
}
int x[maxn], y[maxn], z[maxn], s[maxn], c[maxn], n, m, a[maxn], b[maxn], r[maxn], len;
IL void NTT(RG int *p, RG int m, RG int opt){
RG int l = 0, n = 1;
for(; n < m; n <<= 1) ++l;
for(RG int i = 0; i < n; ++i) r[i] = (r[i >> 1] >> 1) | ((i & 1) << (l - 1));
for(RG int i = 0; i < n; ++i) if(r[i] < i) swap(p[r[i]], p[i]);
for(RG int i = 1; i < n; i <<= 1){
RG int wn = Pow(g, phi / (i << 1));
if(opt == -1) wn = Pow(wn, mod - 2);
for(RG int j = 0, t = i << 1; j < n; j += t)
for(RG int k = 0, w = 1; k < i; ++k, w = 1LL * w * wn % mod){
RG int x = p[j + k], y = 1LL * w * p[j + k + i] % mod;
p[j + k] = (x + y) % mod, p[j + k + i] = (x - y + mod) % mod;
}
}
if(opt == -1){
RG int inv = Pow(n, mod - 2);
for(RG int i = 0; i < n; ++i) p[i] = 1LL * p[i] * inv % mod;
}
}
IL void Inv(RG int *p, RG int *q, RG int num){
if(num == 1){
q[0] = Pow(p[0], mod - 2);
return;
}
Inv(p, q, num >> 1);
for(RG int i = 0; i < num; ++i) a[i] = p[i], b[i] = q[i];
RG int l = num << 1;
NTT(a, l, 1), NTT(b, l, 1);
for(RG int i = 0; i < l; ++i) a[i] = 1LL * a[i] * b[i] % mod * b[i] % mod;
NTT(a, l, -1);
for(RG int i = 0; i < num; ++i) q[i] = ((2 * q[i] - a[i]) % mod + mod) % mod;
for(RG int i = 0; i < l; ++i) a[i] = b[i] = 0;
}
int main(){
n = Input(), m = Input();
for(RG int i = 0; i <= n; ++i) y[i] = Input();
for(RG int i = 0; i <= m; ++i) x[i] = Input();
reverse(x, x + m + 1), reverse(y, y + n + 1);
for(RG int i = 0; i <= n - m; ++i) s[i] = x[i];
for(len = 1; len <= n - m; len <<= 1);
Inv(s, z, len);
for(len = 1; len <= (n - m) << 1; len <<= 1);
for(RG int i = 0; i <= n - m; ++i) a[i] = y[i];
for(RG int i = 0; i <= n - m; ++i) b[i] = z[i];
len <<= 1;
NTT(a, len, 1), NTT(b, len, 1);
for(RG int i = 0; i < len; ++i) b[i] = 1LL * b[i] * a[i] % mod;
NTT(b, len, -1), reverse(b, b + n - m + 1);
for(RG int i = 0; i <= n - m; ++i) c[i] = b[i], printf("%d ", c[i]);
puts(""), reverse(y, y + n + 1), reverse(x, x + m + 1);
for(RG int i = 0; i < len; ++i) a[i] = b[i] = 0;
for(len = 1; len <= n; len <<= 1);
for(RG int i = 0; i <= n; ++i) a[i] = x[i];
for(RG int i = 0; i <= n - m; ++i) b[i] = c[i];
NTT(a, len, 1), NTT(b, len, 1);
for(RG int i = 0; i < len; ++i) a[i] = 1LL * a[i] * b[i] % mod;
NTT(a, len, -1);
for(RG int i = 0; i < m; ++i) y[i] = (y[i] - a[i] + mod) % mod, printf("%d ", y[i]);
return 0;
}
多项式开方
给定\(B(x)\),求\(A(x)\)使\(A^2(x)=B(x)\)
写成
\]
然后
\]
是可以求的,好像是什么二次剩余
留坑在这里以后补
考虑求
\]
令
\]
那么
\]
\]
\]
\]
\]
\]
同样的还是倍增求
多项式ln
设\(B(x)=ln(A(x))\)
同时求导
就是
\]
那么多项式求导,然后多项式求逆,然后多项式积分就好了
多项式exp
设\(B(x)=e^{A(x)}\)
那么
\]
牛顿迭代
得
\]
多项式求幂
设\(B(x)=A^k(x)\)
那么\(ln(B(x))=kln(A(x))\)
然后就是求\(ln\)然后\(exp\)就好了
模板!!!
COGS2189. [HZOI 2015] 帕秋莉的超级多项式
# include <bits/stdc++.h>
# define RG register
# define IL inline
# define Fill(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long ll;
IL int Input(){
RG int x = 0, z = 1; RG char c = getchar();
for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
return x * z;
}
const int maxn(8e5 + 5);
const int mod(998244353);
const int phi(998244352);
const int inv2(499122177);
const int g(3);
int a[maxn], b[maxn], c[maxn], d[maxn], r[maxn];
IL int Pow(RG ll x, RG ll y){
RG ll ret = 1;
for(; y; y >>= 1, x = x * x % mod)
if(y & 1) ret = ret * x % mod;
return ret;
}
IL void NTT(RG int *p, RG int m, RG int opt){
RG int n = 1, l = 0;
for(; n < m; n <<= 1) ++l;
for(RG int i = 0; i < n; ++i) r[i] = (r[i >> 1] >> 1) | ((i & 1) << (l - 1));
for(RG int i = 0; i < n; ++i) if(r[i] < i) swap(p[i], p[r[i]]);
for(RG int i = 1; i < n; i <<= 1){
RG int t = i << 1, wn = Pow(g, phi / t);
if(opt == -1) wn = Pow(wn, mod - 2);
for(RG int j = 0; j < n; j += t)
for(RG int k = 0, w = 1; k < i; ++k, w = 1LL * w * wn % mod){
RG int x = p[k + j], y = 1LL * w * p[k + j + i] % mod;
p[k + j] = (x + y) % mod, p[k + j + i] = (x - y + mod) % mod;
}
}
if(opt == -1){
RG int inv = Pow(n, mod - 2);
for(RG int i = 0; i < n; ++i) p[i] = 1LL * p[i] * inv % mod;
}
}
IL void Inv(RG int *p, RG int *q, RG int len){
if(len == 1){
q[0] = Pow(p[0], mod - 2);
return;
}
Inv(p, q, len >> 1);
for(RG int i = 0; i < len; ++i) a[i] = p[i], b[i] = q[i];
RG int tmp = len << 1;
NTT(a, tmp, 1), NTT(b, tmp, 1);
for(RG int i = 0; i < tmp; ++i) a[i] = 1LL * a[i] * b[i] % mod * b[i] % mod;
NTT(a, tmp, -1);
for(RG int i = 0; i < len; ++i) q[i] = ((2 * q[i] - a[i]) % mod + mod) % mod;
for(RG int i = 0; i < tmp; ++i) a[i] = b[i] = 0;
}
IL void Sqrt(RG int *p, RG int *q, RG int len){
if(len == 1){
q[0] = sqrt(p[0]); //???
return;
}
Sqrt(p, q, len >> 1), Inv(q, c, len);
RG int tmp = len << 1;
for(RG int i = 0; i < len; ++i) a[i] = p[i];
NTT(a, tmp, 1), NTT(c, tmp, 1);
for(RG int i = 0; i < tmp; ++i) a[i] = 1LL * a[i] * c[i] % mod;
NTT(a, tmp, -1);
for(RG int i = 0; i < len; ++i) q[i] = 1LL * (q[i] + a[i]) % mod * inv2 % mod;
for(RG int i = 0; i < tmp; ++i) a[i] = c[i] = 0;
}
IL void ICalc(RG int *p, RG int *q, RG int len){
q[len - 1] = 0;
for(RG int i = 1; i < len; ++i) q[i - 1] = 1LL * p[i] * i % mod;
}
IL void Calc(RG int *p, RG int *q, RG int len){
q[0] = 0;
for(RG int i = 1; i < len; ++i) q[i] = 1LL * Pow(i, mod - 2) * p[i - 1] % mod;
}
IL void Ln(RG int *p, RG int *q, RG int len){
Inv(p, c, len), ICalc(p, a, len);
RG int tmp = len << 1;
NTT(c, tmp, 1), NTT(a, tmp, 1);
for(RG int i = 0; i < tmp; ++i) c[i] = 1LL * c[i] * a[i] % mod;
NTT(c, tmp, -1), Calc(c, q, len);
for(RG int i = 0; i < tmp; ++i) a[i] = c[i] = 0;
}
IL void Exp(RG int *p, RG int *q, RG int len){
if(len == 1){
q[0] = 1;
return;
}
Exp(p, q, len >> 1), Ln(q, b, len);
for(RG int i = 0; i < len; ++i) b[i] = (mod - b[i] + p[i]) % mod, c[i] = q[i];
b[0] = (b[0] + 1) % mod;
RG int tmp = len << 1;
NTT(b, tmp, 1), NTT(c, tmp, 1);
for(RG int i = 0; i < tmp; ++i) b[i] = 1LL * b[i] * c[i] % mod;
NTT(b, tmp, -1);
for(RG int i = 0; i < len; ++i) q[i] = b[i];
for(RG int i = 0; i < tmp; ++i) b[i] = c[i] = 0;
}
IL void CalcPow(RG int *p, RG int *q, RG int len, RG int y){
Ln(p, d, len);
for(RG int i = 0; i < len; ++i) d[i] = 1LL * d[i] * y % mod;
Exp(d, q, len);
for(RG int i = 0; i < len; ++i) d[i] = 0;
}
int f[maxn], h[maxn], n, k, len;
IL void Record(){
for(RG int i = 0; i < len; ++i) f[i] = h[i], h[i] = 0;
}
int main(){
freopen("polynomial.in", "r", stdin);
freopen("polynomial.out", "w", stdout);
n = Input() - 1, k = Input();
for(RG int i = 0; i <= n; ++i) f[i] = Input();
for(len = 1; len <= n; len <<= 1);
Sqrt(f, h, len), Record();
Inv(f, h, len), Record();
Calc(f, h, n + 1), Record();
Exp(f, h, len), Record();
Inv(f, h, len), Record();
f[0] = (f[0] + 1) % mod;
Ln(f, h, len), Record();
f[0] = (f[0] + 1) % mod;
CalcPow(f, h, len, k), Record();
ICalc(f, h, n + 1);
for(RG int i = 0; i <= n; ++i) printf("%d ", h[i]);
return 0;
}
牛顿迭代,多项式求逆,除法,开方,exp,ln,求幂的更多相关文章
- [模板] 多项式: 乘法/求逆/分治fft/微积分/ln/exp/幂
多项式 代码 const int nsz=(int)4e5+50; const ll nmod=998244353,g=3,ginv=332748118ll; //basic math ll qp(l ...
- luogu P4726 多项式指数函数(模板题FFT、多项式求逆、多项式对数函数)
手动博客搬家: 本文发表于20181127 08:39:42, 原地址https://blog.csdn.net/suncongbo/article/details/84559818 题目链接: ht ...
- 树状数组求逆序对:POJ 2299、3067
前几天开始看树状数组了,然后开始找题来刷. 首先是 POJ 2299 Ultra-QuickSort: http://poj.org/problem?id=2299 这题是指给你一个无序序列,只能交换 ...
- [CF 351B]Jeff and Furik[归并排序求逆序数]
题意: 两人游戏, J先走. 给出一个1~n的排列, J选择一对相邻数[题意!!~囧], 交换. F接着走, 扔一硬币, 若正面朝上, 随机选择一对降序排列的相邻数, 交换. 若反面朝上, 随机选择一 ...
- Ultra-QuickSort(树状数组求逆序对数)
Ultra-QuickSort 题目链接:http://poj.org/problem?id=2299 Time Limit: 7000MS Memory Limit: 65536K Total ...
- 求逆序对常用的两种算法 ----归并排 & 树状数组
网上看了一些归并排求逆序对的文章,又看了一些树状数组的,觉得自己也写一篇试试看吧,然后本文大体也就讲个思路(没有例题),但是还是会有个程序框架的 好了下面是正文 归并排求逆序对 树状数组求逆序对 一. ...
- 求逆序对 ----归并排 & 树状数组
网上看了一些归并排求逆序对的文章,又看了一些树状数组的,觉得自己也写一篇试试看吧,然后本文大体也就讲个思路(没有例题),但是还是会有个程序框架的 好了下面是正文 归并排求逆序对 树状数组求逆序对 一. ...
- 51 Nod 1107 斜率小于0的连线数量 (转换为归并求逆序数或者直接树状数组,超级详细题解!!!)
1107 斜率小于0的连线数量 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 二维平面上N个点之间共有C(n,2)条连线.求这C(n,2)条线中斜率小于0的线 ...
- 多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)
预备知识:FFT/NTT 多项式的逆 给定一个多项式 F(x)F(x)F(x),请求出一个多项式 G(x)G(x)G(x),满足 F(x)∗G(x)≡1(mod xn)F(x)*G(x) \equiv ...
随机推荐
- python 简单爬虫(beatifulsoup)
---恢复内容开始--- python爬虫学习从0开始 第一次学习了python语法,迫不及待的来开始python的项目.首先接触了爬虫,是一个简单爬虫.个人感觉python非常简洁,相比起java或 ...
- [原创] Laravel 启动流程
目录 1. 程序启动准备 1.1 容器基础配置 1.2 核心类绑定 1.3 实例化 Http 核心类 2. 请求实例化 3. 请求处理 3.1 请求处理环境初始化 1. 环境监测 \Illuminat ...
- 剑指offer——面试题16:数值的整数次方
// 面试题16:数值的整数次方 // 题目:实现函数double Power(double base, int exponent),求base的exponent // 次方.不得使用库函数,同时不需 ...
- GIF图制作
一.安装image 首先在cmd中敲入代码pip install imageio,以便制作动图 二.安装完之后便可读取gif了 在idle中输入代码 import imageio savename = ...
- $bzoj1014-JSOI2008$ 火星人$prefix$ $splay$ $hash$
题面描述 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:\(madamimadam\),我们将这个字符串的各个字符予以标号: 序号 1 2 3 4 5 6 7 8 ...
- hive DML
1.load files into tables 把文件中的数据加载到表中(表必须先建好) 语法是: load data [local] inpath 'filepath' [overwrite] i ...
- app接口,如何保证是由app内部调用而非外部模拟post请求调用。
在爬虫快手主播信息的时候,发现只要我改动一下参数,比如第一页 page=1的时候,需要爬下一页,把page改为2发现提示sign验证失败了 也就是说,快手在开发的时候考虑了有人抓包到接口后,通过修改参 ...
- <asp:FileUpload>控件 获取不到文件名
<asp:FileUpload>控件 放在了<asp:UpdatePanel>控件中会导致获取不到文件名.
- Android 开发 命名规范(基础回顾)
标识符命名法标识符命名法最要有四种: 1 驼峰(Camel)命名法:又称小驼峰命名法,除首单词外,其余所有单词的第一个字母大写. 2 帕斯卡(pascal)命名法:又称大驼峰命名法,所有单词的第一个字 ...
- oracle中斜杠(/)的含义
斜杠就是让服务器执行前面所写的sql脚本.如果是普通的select语句,一个分号,就可以执行了.但是如果是存储过程,那么遇到分号,就不能马上执行了.这个时候,就需要通过斜杠(/)来执行. 1 2 3 ...