\(\mathcal{Description}\)

  Link.

  给定 \(n\) 次多项式 \(F(x)\),在模 \(998244353\) 意义下求

\[G(x)\equiv\left\{\left[1+\ln\left(2+F(x)-F(0)-\exp \int \frac{1}{\sqrt{F(t)}}\text dt\right)\right]^k\right\}'\pmod{x^n}
\]

其中保证 \(F(0)\) 是模数的二次剩余,开根取模意义下较小常数项值。

  \(n\le10^5\)

\(\mathcal{Solution}\)

  先这样再那样,嗯。

  涉及到多项式 \(\exp\),\(\ln\),求逆,开根,求幂,积分求导,具体推导可以看 这里 哟~

\(\mathcal{Code}\)

/*~Rainybunny~*/

#include <cstdio>
#include <cassert>
#include <cstdlib>
#include <algorithm> #define rep( i, l, r ) for ( int i = l, rep##i = r; i <= rep##i; ++i )
#define per( i, r, l ) for ( int i = r, per##i = l; i >= per##i; --i ) const int MAXL = 1 << 18, MOD = 998244353, INV2 = MOD + 1 >> 1; inline void subeq( int& a, const int b ) { ( a -= b ) < 0 && ( a += MOD ); }
inline int sub( int a, const int b ) { return ( a -= b ) < 0 ? a + MOD : a; }
inline int mul( const long long a, const int b ) { return int( a * b % MOD ); }
inline int add( int a, const int b ) { return ( a += b ) < MOD ? a : a - MOD; }
inline void addeq( int& a, const int b ) { ( a += b ) >= MOD && ( a -= MOD ); }
inline int mpow( int a, int b ) {
int ret = 1;
for ( ; b; a = mul( a, a ), b >>= 1 ) ret = mul( ret, b & 1 ? a : 1 );
return ret;
} namespace QResidue { /*
* PolyOper::polySqrt() need this.
* */ int SQRI; struct Complex {
int x, y;
Complex(): x( 0 ), y( 0 ) {}
Complex( const int tx, const int ty ): x( tx ), y( ty ) {}
inline Complex operator * ( const Complex& c ) const {
return Complex( add( mul( x, c.x ), mul( SQRI, mul( y, c.y ) ) ),
add( mul( x, c.y ), mul( y, c.x ) ) );
}
}; inline bool isResidue( const int x ) { return mpow( x, MOD - 1 >> 1 ) == 1; } inline Complex cpow( Complex a, int b ) {
Complex ret( 1, 0 );
for ( ; b; a = a * a, b >>= 1 ) if ( b & 1 ) ret = ret * a;
return ret;
} inline int residue( const int n ) {
if ( !n ) return 0;
if ( !isResidue( n ) ) return -1;
srand( 20120712 ); int a = rand() % MOD;
while ( !a || isResidue( sub( mul( a, a ), n ) ) ) a = rand() % MOD;
SQRI = sub( mul( a, a ), n );
int ret = cpow( Complex( a, 1 ), MOD + 1 >> 1 ).x;
return ret < MOD - ret ? ret : MOD - ret;
} } // namespace QResidue. namespace PolyOper { /* *
* - call init() before any operation;
* - for `poly(n,u,w)', w can't be u;
* - for `poly(n,u,w)', it will only access u[0..n-1] and w[0..n-1];
* - for `poly(n,u,w)', there's no need to clear w before calling them.
* - remember that `n' is always 2^k.
* */ const int MG = 3;
int inv[MAXL + 5], omega[20][MAXL]; inline void init() {
inv[1] = 1;
rep ( i, 2, MAXL + 3 ) inv[i] = mul( MOD - MOD / i, inv[MOD % i] );
rep ( i, 0, 17 ) {
int* oi = omega[i];
oi[0] = 1, oi[1] = mpow( MG, MOD - 1 >> i >> 1 );
rep ( j, 2, ( 1 << i ) - 1 ) oi[j] = mul( oi[j - 1], oi[1] );
}
} inline void ntt( const int n, int* u, const int type ) {
static int rev[MAXL]; rev[0] = 0;
int lgn = 1; for ( ; 1 << lgn < n; ++lgn );
rep ( i, 1, n - 1 ) rev[i] = rev[i >> 1] >> 1 | ( i & 1 ) << lgn >> 1;
rep ( i, 1, n - 1 ) if ( i < rev[i] ) {
u[i] ^= u[rev[i]] ^= u[i] ^= u[rev[i]];
}
for ( int i = 0, stp = 1; stp < n; ++i, stp <<= 1 ) {
int* oi = omega[i];
for ( int j = 0; j < n; j += stp << 1 ) {
rep ( k, j, j + stp - 1 ) {
int ev = u[k], ov = mul( oi[k - j], u[k + stp] );
u[k] = add( ev, ov ), u[k + stp] = sub( ev, ov );
}
}
}
if ( !~type ) {
int ivn = MOD - ( MOD - 1 ) / n;
rep ( i, 0, n - 1 ) u[i] = mul( u[i], ivn );
std::reverse( u + 1, u + n );
}
} inline void polyInv( const int n, const int* u, int* w ) {
static int tmp[2][MAXL];
if ( n == 1 ) return void( w[0] = mpow( u[0], MOD - 2 ) );
polyInv( n >> 1, u, w );
rep ( i, 0, ( n >> 1 ) - 1 ) tmp[0][i] = w[i], tmp[1][i] = u[i];
rep ( i, n >> 1, n - 1 ) tmp[0][i] = 0, tmp[1][i] = u[i];
rep ( i, n, ( n << 1 ) - 1 ) tmp[0][i] = tmp[1][i] = 0;
ntt( n << 1, tmp[0], 1 ), ntt( n << 1, tmp[1], 1 );
rep ( i, 0, ( n << 1 ) - 1 ) {
tmp[0][i] = mul( tmp[0][i], sub( 2, mul( tmp[0][i], tmp[1][i] ) ) );
}
ntt( n << 1, tmp[0], -1 );
rep ( i, 0, n - 1 ) w[i] = tmp[0][i];
} inline void polyInt( const int n, const int* u, int* w ) {
w[0] = 0;
rep ( i, 1, n ) w[i] = mul( u[i - 1], inv[i] );
} inline void polyDer( const int n, const int* u, int* w ) {
w[n - 1] = 0;
rep ( i, 0, n - 2 ) w[i] = mul( u[i + 1], i + 1 );
} inline void polyLn( const int n, const int* u, int* w ) {
static int tmp[2][MAXL]; assert( u[0] == 1 );
polyDer( n, u, tmp[0] ), polyInv( n, u, tmp[1] );
rep ( i, n, ( n << 1 ) - 1 ) tmp[0][i] = tmp[1][i] = 0;
ntt( n << 1, tmp[0], 1 ), ntt( n << 1, tmp[1], 1 );
rep ( i, 0, ( n << 1 ) - 1 ) tmp[0][i] = mul( tmp[0][i], tmp[1][i] );
ntt( n << 1, tmp[0], -1 ), polyInt( n - 1, tmp[0], w );
} inline void polyExp( const int n, const int* u, int* w ) {
static int tmp[2][MAXL];
if ( n == 1 ) return assert( !u[0] ), w[0] = 1, void();
polyExp( n >> 1, u, w );
rep ( i, 0, ( n >> 1 ) - 1 ) tmp[0][i] = w[i], tmp[1][i] = 0;
rep ( i, n >> 1, ( n << 1 ) - 1 ) tmp[0][i] = tmp[1][i] = 0;
polyLn( n, tmp[0], tmp[1] ), tmp[1][0] = sub( tmp[1][0], 1 );
rep ( i, 0, n - 1 ) tmp[1][i] = sub( u[i], tmp[1][i] );
ntt( n << 1, tmp[0], 1 ), ntt( n << 1, tmp[1], 1 );
rep ( i, 0, ( n << 1 ) - 1 ) tmp[0][i] = mul( tmp[0][i], tmp[1][i] );
ntt( n << 1, tmp[0], -1 );
rep ( i, 0, n - 1 ) w[i] = tmp[0][i];
} inline void polySqrt( const int n, const int* u, int* w ) {
static int tmp[2][MAXL];
if ( n == 1 ) return assert( ~( w[0] = QResidue::residue( u[0] ) ) );
polySqrt( n >> 1, u, w ); rep ( i, n >> 1, n - 1 ) w[i] = 0;
polyInv( n, w, tmp[0] );
rep ( i, n, ( n << 1 ) - 1 ) tmp[0][i] = tmp[1][i] = 0;
rep ( i, 0, n - 1 ) tmp[1][i] = u[i];
ntt( n << 1, tmp[0], 1 ), ntt( n << 1, tmp[1], 1 );
rep ( i, 0, ( n << 1 ) - 1 ) tmp[0][i] = mul( tmp[0][i], tmp[1][i] );
ntt( n << 1, tmp[0], -1 );
rep ( i, 0, n - 1 ) w[i] = mul( add( w[i], tmp[0][i] ), INV2 );
} } // namespace PolyOper. /*** templates are above. ***/ int n, k, tmpF[MAXL + 5], F[MAXL + 5], G[MAXL + 5]; int main() {
PolyOper::init();
scanf( "%d %d", &n, &k ), ++n;
rep ( i, 0, n - 1 ) scanf( "%d", &F[i] ), tmpF[i] = F[i];
int len = 1; for ( ; len < n; len <<= 1 ); PolyOper::polySqrt( len, F, G );
PolyOper::polyInv( len, G, F );
PolyOper::polyInt( len, F, G );
PolyOper::polyExp( len, G, F );
rep ( i, 0, len - 1 ) F[i] = sub( tmpF[i], F[i] );
F[0] = sub( add( F[0], 2 ), tmpF[0] );
PolyOper::polyLn( len, F, G );
G[0] = add( G[0], 1 );
PolyOper::polyLn( len, G, F );
rep ( i, 0, len - 1 ) F[i] = mul( F[i], k );
PolyOper::polyExp( len, F, G );
PolyOper::polyDer( len, G, F ); rep ( i, 0, n - 2 ) printf( "%d%c", F[i], i + 2 < n ? ' ' : '\n' );
return 0;
}

Solution -「LOJ #150」挑战多项式 ||「模板」多项式全家桶的更多相关文章

  1. 「LOJ 556 Antileaf's Round」咱们去烧菜吧

    「LOJ 556 Antileaf's Round」咱们去烧菜吧 最近在看 jcvb 的生成函数课件,顺便切一切上面讲到的内容的板子题,这个题和课件上举例的背包计数基本一样. 解题思路 首先列出答案的 ...

  2. 「WC2016」挑战NPC

    「WC2016」挑战NPC 解题思路 这个题建图非常厉害,带花树什么的只会口胡根本写不动,所以我写了机房某大佬教我的乱搞. 考虑把一个筐 \(x\) 拆成 \(x1,x2,x3\) 三个点,且这三个点 ...

  3. 「LOJ#10051」「一本通 2.3 例 3」Nikitosh 和异或(Trie

    题目描述 原题来自:CODECHEF September Challenge 2015 REBXOR 1​​≤r​1​​<l​2​​≤r​2​​≤N,x⨁yx\bigoplus yx⨁y 表示 ...

  4. 「LOJ#10056」「一本通 2.3 练习 5」The XOR-longest Path (Trie

    #10056. 「一本通 2.3 练习 5」The XOR-longest Path 题目描述 原题来自:POJ 3764 给定一棵 nnn 个点的带权树,求树上最长的异或和路径. 输入格式 第一行一 ...

  5. 火爆的文字游戏你玩了吗?「GitHub 热点速览 v.22.06」

    不知道你有没有被 Wordle 这款游戏刷屏,在本期热点速览的特推部分选了一个 React 编写的开源版本同你分享,而本次公众号摘要也是一个提示, 只不过这个只能盲猜了.别小瞧 Wordle 这个游戏 ...

  6. 用 Java 写个塔防游戏「GitHub 热点速览 v.21.37」

    作者:HelloGitHub-小鱼干 本周 GitHub Trending 的主题词是:多语言.本周特推的 C 语言教程是大家都知道的阮一峰编写的,想必和他之前的技术文章类似,能起到科普作用.再来时 ...

  7. 大型项目源码集合「GitHub 热点速览 v.21.39」

    作者:HelloGitHub-小鱼干 代码,尤其是优雅规范的代码,一直都是学习编程技巧的捷径.虽然有实用的代码小片段,能拯救当前业务的燃眉之急,但是真要去提升自己的技能还是得从大型的项目,尤其是有一定 ...

  8. GitHub 开源的小工具「GitHub 热点速览 v.21.45」

    作者:HelloGitHub-小鱼干 Copilot 是 GitHub 官方出品的代码自动补全工具,之前使用该工具需要有一定的要求.而本周靠 2k+ star 上热点的 copilot-docs 则是 ...

  9. 天冷了,任务栏养只猫吧「GitHub 热点速览 v.21.46」

    作者:HelloGitHub-小鱼干 运动能带来热量,盘猫也是,RunCat_for_windows 是一只奔跑在任务栏的猫,一定能给你的电脑带来一丝冬日的温暖.当然送温暖的除了任务栏小猫咪之外,还有 ...

随机推荐

  1. spring cloud Zuul + 路由熔断【服务降级】 --- 心得

    1.前言 刚入门 时,使用 ribbon + hystrix + restTemplate  ,实现了简单的 接口访问 + 客户端负载均衡 + 服务熔断保护 : 然后学习了 feign ,整合了  r ...

  2. centos7 修改网卡信息

    修改网卡配置文件 vim /etc/sysconfig/network-scripts/ifcfg-eth0 有一些不是eth0 也可能是ens33 修改完成后使用下面命令进行重启 systemctl ...

  3. 微服务架构 | 3.2 Alibaba Nacos 注册中心

    目录 前言 1. Nacos 基础知识 1.1 Nacos 命名方式 1.2 Nasoc 是什么 1.3 Nacos 的 4 个关键特性 1.4 Nacos 生态图 1.5 Nacos 架构图 1.6 ...

  4. [STM32F4xx 学习] 如何在RAM中调试程序

    在RAM中调试程序指的是将程序下载到RAM里面(而不是Flash里面),然后在RAM中执行程序.调试. 为什么要在RAM中调试程序?总结起来有以下两点原因: 1. Flash 擦写次数有限,STM32 ...

  5. golang中的go get命令

    ### 下载指定版本 go get k8s.io/klog@v1.0.0 go get 命令可以借助代码管理工具通过远程拉取或更新代码包及其依赖包,并自动完成编译和安装. 这个命令在内部实际上分成了两 ...

  6. 微信小程序入门教程之四:API 使用

    今天是这个系列教程的最后一篇. 上一篇教程介绍了,小程序页面如何使用 JavaScript 脚本.有了脚本以后,就可以调用微信提供的各种能力(即微信 API),从而做出千变万化的页面.本篇就介绍怎么使 ...

  7. java 方法实例

    // 方法 public class Demo { public static void main(String[] args) { m(); m2(2); m3('3', 4); m4(4, 6); ...

  8. clickhouse-mysql数据同步

    clickhouse版本:22.1.2.2 1.Mysql引擎(不推荐) CREATE DATABASE [IF NOT EXISTS] db_name [ON CLUSTER cluster] EN ...

  9. lambda表达式的学习

    Lambda表达式 为什么使用lambda表达式 Lambda表达式可以简化我们的代码,使我们只需要关注主要的代码就可以. //测试用的实体类 public class Employee { priv ...

  10. window-server 服务器解决远程连接

    mstsc 连接远程服务器,出现黑屏的情况: 解决方案: 运行 -> 输入gpedit.msc,进入组策略 -> 计算机配置 -> 管理模板 -> Windows组件 -> ...