Luogu5245 【模板】多项式快速幂(多项式exp)

  A(x)k=eklnA(x),丝毫不懂为什么指数要对p取模,只是写下exp板子。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 600010
#define P 998244353
char getc(){char c=getchar();while ((c<‘A‘||c>‘Z‘)&&(c<‘a‘||c>‘z‘)&&(c<‘0‘||c>‘9‘)) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
	int x=0,f=1;char c=getchar();
	while (c<‘0‘||c>‘9‘) {if (c==‘-‘) f=-1;c=getchar();}
	while (c>=‘0‘&&c<=‘9‘) x=(10ll*x+c-48)%P,c=getchar();
	return x*f;
}
int n,m,a[N],r[N],b[N],c[N],d[N],A[N],B[N],t;
int ksm(int a,int k)
{
	int s=1;
	for (;k;k>>=1,a=1ll*a*a%P) if (k&1) s=1ll*s*a%P;
	return s;
}
int inv(int a){return ksm(a,P-2);}
void DFT(int *a,int n,int g)
{
	for (int i=0;i<n;i++) r[i]=(r[i>>1]>>1)|(i&1)*(n>>1);
	for (int i=0;i<n;i++) if (i<r[i]) swap(a[i],a[r[i]]);
	for (int i=2;i<=n;i<<=1)
	{
		int wn=ksm(g,(P-1)/i);
		for (int j=0;j<n;j+=i)
		{
			int w=1;
			for (int k=j;k<j+(i>>1);k++,w=1ll*w*wn%P)
			{
				int x=a[k],y=1ll*w*a[k+(i>>1)]%P;
				a[k]=(x+y)%P,a[k+(i>>1)]=(x-y+P)%P;
			}
		}
	}
}
void IDFT(int *a,int n)
{
	DFT(a,n,inv(3));
	int u=inv(n);
	for (int i=0;i<n;i++) a[i]=1ll*a[i]*u%P;
}
void mul(int *a,int *b,int n)
{
	DFT(a,n,3),DFT(b,n,3);
	for (int i=0;i<n;i++) a[i]=1ll*a[i]*b[i]%P;
	IDFT(a,n);
}
void Inv(int *a,int *b,int n)
{
	if (n==1) {for (int i=0;i<t;i++) b[i]=0;b[0]=inv(a[0]);return;}
	Inv(a,b,n>>1);
	for (int i=0;i<n;i++) A[i]=a[i];
	for (int i=n;i<(n<<1);i++) A[i]=0;
	n<<=1;
	DFT(A,n,3),DFT(b,n,3);
	for (int i=0;i<n;i++) b[i]=1ll*b[i]*(P+2-1ll*A[i]*b[i]%P)%P;
	IDFT(b,n);
	n>>=1;
	for (int i=n;i<(n<<1);i++) b[i]=0;
}
//G(B(x))=A(x)B(x)-1
//B(x)=B0(x)-G(B0(x))/G‘(B0(x))
//B(x)=B0(x)-(A(x)B0(x)-1)/A(x)
//B(x)=B0(x)(2-A(x)B0(x))
void trans(int *a,int *b,int n){for (int i=n-1;i>=0;i--) b[i]=1ll*a[i+1]*(i+1)%P;}
void dx(int *a,int *b,int n){b[0]=0;for (int i=1;i<n;i++) b[i]=1ll*a[i-1]*inv(i)%P;}
void Ln(int *a,int n)
{
	for (int i=0;i<n;i++) b[i]=c[i]=0;
	trans(a,b,n>>1);
	Inv(a,c,n>>1);
	mul(b,c,n);
	dx(b,a,n);
}
//ln(F(x))=G(x)
//F‘(x)/F(x)=G‘(x)
//dx F‘(x)/F(x)=G(x)
void Exp(int *a,int *b,int n)
{
	if (n==1){b[0]=1;return;}
	Exp(a,b,n>>1);
	for (int i=0;i<(n>>1);i++) B[i]=b[i];
	for (int i=(n>>1);i<n;i++) B[i]=0;
	Ln(B,n);
	for (int i=0;i<n;i++) B[i]=(a[i]-B[i]+P)%P;
	B[0]=(B[0]+1)%P;
	n<<=1;
	for (int i=(n>>1);i<n;i++) B[i]=0;
	mul(b,B,n);
	n>>=1;
	for (int i=n;i<(n<<1);i++) b[i]=0;
}
//exp(A(x))=B(x)
//A(x)=ln(B(x))
//G(B(x))=ln(B(x))-A(x)
//B(x)=B0(x)(A(x)+1-ln(B0(x)))
int main()
{
#ifndef ONLINE_JUDGE
	freopen("a.in","r",stdin);
	freopen("a.out","w",stdout);
	const char LL[]="%I64d\n";
#else
	const char LL[]="%lld\n";
#endif
	n=read(),m=read();
	for (int i=0;i<n;i++) a[i]=read();
	t=1;while (t<=(n<<1)) t<<=1;
	Ln(a,t);
	for (int i=0;i<t;i++) a[i]=1ll*a[i]*m%P;
	Exp(a,d,t);
	for (int i=0;i<n;i++) printf("%d ",d[i]);
	return 0;
}

  

原文地址:https://www.cnblogs.com/Gloid/p/10637253.html

时间: 2024-11-09 03:21:09

Luogu5245 【模板】多项式快速幂(多项式exp)的相关文章

luoguP5219 无聊的水题 I 多项式快速幂

有一个幼儿园容斥:最大次数恰好为 $m=$  最大次数最多为 $m$ - 最大次数最多为 $m-1$. 然后来一个多项式快速幂就好了. code: #include <cmath> #include <cstring> #include <algorithm> #include <cstdio> #include <string> #define ll long long #define ull unsigned long long using

luoguP5245 【模板】多项式快速幂

$B(x)=A^k(x)$ $\Rightarrow \ln B(x)=\ln A^k(x)$ $\Rightarrow \ln B(x)=k \ln A(x)$ $\Rightarrow B(x)=\exp(k \ln A(x))$ code: #include <cmath> #include <cstring> #include <algorithm> #include <cstdio> #include <string> #define

【BZOJ3992】[SDOI2015]序列统计 NTT+多项式快速幂

[BZOJ3992][SDOI2015]序列统计 Description 小C有一个集合S,里面的元素都是小于M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数列,数列中的每个数都属于集合S. 小C用这个生成器生成了许多这样的数列.但是小C有一个问题需要你的帮助:给定整数x,求所有可以生成出的,且满足数列中所有数的乘积mod M的值等于x的不同的数列的有多少个.小C认为,两个数列{Ai}和{Bi}不同,当且仅当至少存在一个整数i,满足Ai≠Bi.另外,小C认为这个问题的答案可能

【模板】快速幂取模

快速幂取模的模板,要注意所有变量都要开成long long类型的防溢出: #include<cstdio> #include<algorithm> #include<cstring> typedef long long LL; const LL mod=1e9+7; using namespace std; LL a,b; LL mi(LL x,LL y) { LL res=1; while(y){ if(y&1) res=res*x%mod; y>>

模板——矩阵快速幂

/************************************************ Author :powatr Created Time :2015-8-5 21:06:30 File Name :b.cpp ************************************************/ #include <cstdio> #include <algorithm> #include <iostream> #include <s

【模板】快速幂

普通的快速幂,用于矩阵的版本稍后更新 1 #include<stdio.h> 2 #define lll long long 3 lll ksm(int,int); 4 int x,n; 5 int main() 6 { 7 scanf("%d%d",&x,&n); 8 printf("%lld",ksm(x,n)); 9 return 0; 10 } 11 lll ksm(int x,int n) 12 { 13 lll ret = x

[模板] 矩阵快速幂

矩阵快速幂是一个快速幂的延伸,但实际上区别不大,主要思想是一样的. 题干: 题目背景 矩阵快速幂 题目描述 给定n*n的矩阵A,求A^k 输入输出格式 输入格式: 第一行,n,k 第2至n+1行,每行n个数,第i+1行第j个数表示矩阵第i行第j列的元素 输出格式: 输出A^k 共n行,每行n个数,第i行第j个数表示矩阵第i行第j列的元素,每个元素模10^9+7 输入输出样例 输入样例#1: 复制 2 1 1 1 1 1 输出样例#1: 复制 1 1 1 1 说明 n<=100, k<=10^1

模板—十进制快速幂

用于指数爆longlong的情况,当然你也可以打高精…… 因为昨天有人提到了慢速乘,感觉挺有用的,就顺便都学了吧,而且省选也用到十进制快速幂了. #include<iostream> #include<cstring> #include<cstdio> #define LL long long using namespace std; char c[100000]; LL a,p,t; LL tenthpow(LL a) { LL ans=1,s=a; while(t&

【模板】 快速幂快速积

1 long long ksj(long long a,long long b,long long c)    //快速积取模 a*b%c  2 { 3     long long ans=0; 4     while(b){ 5         if(b&1) 6             ans=(ans+a)%c; 7         a=(a+a)%c; 8         b>>=1;  9     } 10     return ans; 11 }  12 13 long l