题意:
给多项式和,求次多项式,满足。
luogu传送门
思路:
题意具体可以把多项式当作自变量,每次次幂后,乘的系数。
想要暴力解决问题,试试分块。
令
可以预处理出以及
然后枚举,累加第二个。
然后第二个得到的结果和前面多项式乘,用
大概总时间复杂度?
而且这个常数挺低的,时限也很大。
*注意:我因为预处理问题调了很久,预处理时,可能会爆,讨论版有人说最大设为就不会爆,事实上我的就会,我布吉岛别人怎么写的。
我最后还是改回,每算到一次的值,截断一次(从位开始往后赋值为)。
code:
戳我
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+5;
const int M=100005;
const int L=155;
const int mod=998244353;
int n,m,Blen;
ll A[N],gen[2][N],inv3=332748118,B[L][M],B_[L][M],tb[L][M],tb_[L][M],ans[N],f[N],i_up;
int up,l,rev[N];
ll ksm(ll a,ll b) {ll res=1;for(;b;b>>=1,a=a*a%mod)if(b&1)res=res*a%mod;return res;}
void gt_up(int len) {
up=1,l=0;
while(up<=len) {up<<=1,l++;}
for(int i=1;i<up;i++) {rev[i]=(rev[i>>1]>>1)|((i&1)<<(l-1));}
}
void NTT(ll *a,int op) {
for(int i=0;i<up;i++) {
if(rev[i]>i)swap(a[i],a[rev[i]]);
}
for(int mid=1;mid<up;mid<<=1) {
int len=mid<<1;ll w1=gen[op][len];
for(int l=0;l<up;l+=len) {
ll W=1;
for(int i=0;i<mid;i++,W=W*w1%mod) {
int p=l+i,q=p+mid;
ll x=a[p],y=W*a[q];
a[p]=(x+y)%mod;a[q]=(x-y)%mod;
}
}
}
}
void init() {
scanf("%d%d",&n,&m);n++;m++;
Blen=ceil(sqrt(n));
for(int i=0;i<n;i++)scanf("%lld",&A[i]);
for(int i=0;i<m;i++)scanf("%lld",&B[1][i]),tb[1][i]=B[1][i];
gt_up(n<<1);
i_up=ksm(up,mod-2);
// printf("up=%d\n",up);
gen[0][up]=ksm(3,(mod-1)/up); gen[1][up]=ksm(inv3,(mod-1)/up);
for(int i=up;i;i>>=1) {
gen[0][i>>1]=gen[0][i]*gen[0][i]%mod;
gen[1][i>>1]=gen[1][i]*gen[1][i]%mod;
}
tb[0][0]=B[0][0]=B_[0][0]=tb_[0][0]=1;
NTT(tb[0],0),NTT(tb_[0],0);
NTT(tb[1],0);
for(int i=2;i<=Blen;i++) {
for(int j=0;j<up;j++) B[i][j]=tb[i-1][j]*tb[1][j]%mod;
NTT(B[i],1);
for(int j=0;j<n;j++) tb[i][j]=B[i][j]=B[i][j]*i_up%mod;
for(int j=n;j<up;j++)tb[i][j]=B[i][j]=0;
NTT(tb[i],0);
}
// printf("!%lld!\n",B[1][0]);
// for(int j=0;j<up;j++) tb_[1][j]=tb[Blen][j],B_[1][j]=B[Blen][j];
for(int j=0;j<n;j++) tb_[1][j]=B_[1][j]=B[Blen][j];
// for(int j=0;j<up;j++)printf("!%lld %lld\n",tb_[1][j],B_[Blen][j]);
NTT(tb_[1],0);
for(int i=2;i<Blen;i++) {
for(int j=0;j<up;j++) B_[i][j]=tb_[i-1][j]*tb_[1][j]%mod;
NTT(B_[i],1);
for(int j=0;j<n;j++) tb_[i][j]=B_[i][j]=B_[i][j]*i_up%mod;
for(int j=n;j<up;j++) tb_[i][j]=B_[i][j]=0; //截取
NTT(tb_[i],0);
// printf("i=%d:~~\n",i);
// for(int j=0;j<n;j++) {printf("%lld ",(B_[i][j]+mod)%mod);}
// puts("");
}
}
void solve() {
for(int i=0;i<Blen;i++) {
// printf("i=%d~~~~\n",i);
for(int j=0;j<Blen;j++) {
ll w=A[i*Blen+j];
for(int k=0;k<n;k++) {
f[k]=(f[k]+B[j][k]*w)%mod;
// printf("(B[%d][%d]=%lld) %lld\n",j,k,(B[j][k]+mod)%mod,(f[k]%mod+mod)%mod);
}
}
// for(int k=0;k<up;k++)printf("f[%d] = %lld\n",k,(f[k]%mod+mod)%mod);
NTT(f,0);
for(int k=0;k<up;k++) f[k]=f[k]*tb_[i][k]%mod;
NTT(f,1);
for(int k=0;k<n;k++) {
ans[k]=(ans[k]+f[k]*i_up)%mod;
f[k]=0;
}
for(int k=n;k<up;k++)f[k]=0;
}
for(int i=0;i<n;i++)printf("%lld ",(ans[i]%mod+mod)%mod);
}
int main() {
// freopen("data.in","r",stdin);
// freopen("A.out","w",stdout);
init();
solve();
return 0;
}
ps.说实话,这个东西没什么卵用
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人