1 条题解
-
0
自动搬运
来自洛谷,原作者为

xujindong_
;搬运于
2025-08-24 22:28:50,当前版本为作者最后更新于2025-05-22 17:41:11,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
我们需要维护维护一个长 的动态 FFT,支持单点修改,单点查询 DFT,运算次数 。
如果直接在外面用数据结构的手法维护,因为 FFT 有 ,最后很难纯正根号。考虑对 FFT 的结构动手。高低位分治,在 FFT 的某一层中,每对数 若只有这一位不同,会变为 。只做 层,每个数会贡献到 个位置。维护 FWT 做完前 层的结果,修改和查询都只涉及 个位置。系数容易比较两个数的位计算。复杂度 ,其中 的常数是 ,可以通过。
下面的代码是经过位逆序置换后的 DIT,可能和正常写法有差别。
#include<bits/stdc++.h> using namespace std; const int n=4096,bn=64,bd=6,mod=998244353,w=63912897; int m,l,wn[4096],rev[4096],a[4096],f[4096],c1[64][64],c2[4096]; ostringstream ans; void modify(int x,int k){ ans<<"S "<<k<<'\n',l++; ans<<"* "<<a[x]<<' '<<l-1<<'\n',l++; ans<<"- "<<l-1<<' '<<a[x]<<'\n',l++; a[x]=l-2,k=l-1; for(int i=0;i<bn;i++){ ans<<"* "<<k<<' '<<c1[x>>bd][i]<<'\n',l++; ans<<"+ "<<f[i<<bd|(x&(bn-1))]<<' '<<l-1<<'\n',l++; f[i<<bd|(x&(bn-1))]=l-1; } } void query(int x){ int pos=l++; ans<<"S 0\n",x=rev[x]; for(int i=1,b;i<bn;i++)b=__builtin_ctz(i),c2[i]=(c2[i&(i-1)]+(rev[x>>(b+1)]>>1)+(x>>b&1?n/2:0))%n; for(int i=0;i<bn;i++){ ans<<"* "<<f[(x&(n-bn))|i]<<' '<<c2[i]<<'\n',l++; ans<<"+ "<<pos<<' '<<l-1<<'\n',pos=l++; } ans<<"< "<<pos<<'\n',l++; } int main(){ wn[0]=1; for(int i=1;i<n;i++)wn[i]=1ll*w*wn[i-1]%mod,rev[i]=rev[i>>1]>>1|(i&1?n>>1:0); for(int i=0;i<n;i++)ans<<"S "<<wn[i]<<'\n',l++; for(int x=0;x<bn;x++)for(int y=0;y<bn;y++)for(int i=0;i<bd;i++)if(x>>i&1)c1[x][y]=(c1[x][y]+(rev[y>>(i+1)]>>1)+(y>>i&1?n/2:0))%n; cin>>m; for(int i=0;i<n;i++)ans<<(i<m?">\n":"S 0\n"),a[i]=f[i]=l++; for(int i=n>>1;i>=bn;i>>=1){ for(int j=0,p=0;j<n;j+=i<<1,p++){ for(int k=j,y;k<j+i;k++){ ans<<"* "<<f[k+i]<<' '<<(rev[p]>>1)<<'\n',y=l++; ans<<"- "<<f[k]<<' '<<y<<'\n',f[k+i]=l++; ans<<"+ "<<f[k]<<' '<<y<<'\n',f[k]=l++; } } } cin>>m; for(int i=1,opt,x,k;i<=m;i++){ cin>>opt; if(opt==1)cin>>x>>k,modify(x,k); else cin>>k,k%=n,query(k); } return cout<<l<<'\n'<<ans.str(),0; }
- 1
信息
- ID
- 6301
- 时间
- 2000ms
- 内存
- 500MiB
- 难度
- 7
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者