2024.11.8 鲜花
Moon Halo
Some deserts on this planet were oceans once 这颗星球上的一些沙漠曾是海洋 Somewhere shrouded by the night, the sun will shine 被黑夜笼罩的地方,也会迎来光明 Sometimes I see a dying bird fall to the ground 偶尔也会见到濒死的鸟跌落地面 But it used to fly so high 但它也曾展翅高飞 I thought I were no more than a bystander till I felt a touch so real 我本以为我不过是个旁观者 直到我感觉到如此真实的触觉 I will no longer be a transient when I see smiles with tears 当我看到人们含泪的微笑 我便不再是个匆匆过客 If I have never known the sore of farewell and pain of sacrifices 如果不曾知晓生离死别的伤痛 What else should I engrave on my mind 我又该将什么铭记于心 Frozen into icy rocks, that's how it starts 冰冻成石一般的开端 Crumbled like the sands of time, that's how it ends 沙漏崩落一般的终结 Every page of tragedy is thrown away burned out in the flame 悲剧的每一页已被焚烧殆尽 A shoulder for the past 给过往一个肩膀 Let out the cries imprisoned for so long 让久被禁锢的哭泣得以放声 A pair of wings for me at this moment 给此刻的自己一双翅膀 To soar above this world 翱翔于世界之上 Turn into a shooting star that briefly shines but warms up every heart 化为一颗流星,给每个心灵一瞬的希望 May all the beauty be blessed 愿所有的美好都能得到祝福 May all the beauty be blessed 愿所有的美好都能得到祝福 I will never go 我不会离开 There's a way back home 这就是我们的归途 Brighter than tomorrow and yesterday 比过往与未来都要更加闪耀着 May all the beauty be blessed 愿所有的美好都能得到祝福 Wave good-bye to the past when hope and faith have grown so strong and sound 当希望和信念羽翼丰满,就向昨日告别吧 Unfold this pair of wings for me again 再一次为我张开这双羽翼 To soar above this world 翱翔于世界之上 Turned into a moon that always tells the warmth and brightness of the sun 化为月亮长久地传达着太阳的光耀 May all the beauty be blessed 愿所有的美好都能得到祝福 May all the beauty be blessed 愿所有的美好都能得到祝福
你说得对,没人问我,但这是我们初一第一首起床铃
sosdp,FMT,FWT 下
不是,怎么 FMT 只有板子和不可做题啊!!!
那就先放板子吧:CF582E Boolean Function
solution
起手建表达式树。
但是队奶告诉我可以 FMT 可以直接求异或卷积,快快推荐一下。
感觉放课件太魔怔了,想看的可以看 this,就复述一下把。
考虑前缀和时第
类似定义新运算,依次对第
逆运算是显然的
于是我们用这个做莫变即可。
证明:
于是就有真正的板子了:P4717 【模板】快速莫比乌斯/沃尔什变换 (FMT/FWT)
放个代码:
Code
#include<bits/stdc++.h> using namespace std; using llt=long long; using llf=long double; using ull=unsigned long long; #define endl '\n' #ifdef LOCAL FILE *InFile=freopen("in_out/in.in","r",stdin),*OutFile=freopen("in_out/out.out","w",stdout); #else FILE *InFile=stdin,*OutFile=stdout; #endif const int N=1<<17|3,MOD=998244353,Inv=(MOD+1)/2; int Add(int a,int b){return (a+=b)>=MOD?a-MOD:a;} int Sub(int a,int b){return (a-=b)<0?a+MOD:a;} int ca[N],cb[N],a[N],b[N],n; void Fmt(int *f,const function<void(int &,int &)> &F){for(int i=1;i<n;i<<=1) for(int j=0;j<n;++j) if(j&i) F(f[j^i],f[j]);} const function<void(int &,int &)> Or=[](int &a,int &b){b=Add(a,b);}, And=[](int &a,int &b){a=Add(a,b);}, Xor=[](int &a,int &b){int t=a; a=Add(a,b),b=Sub(t,b);}; void Cp(){memcpy(a,ca,sizeof a),memcpy(b,cb,sizeof b);} void Mrg(){for(int i=1;i<=n;++i) a[i]=1ll*a[i]*b[i]%MOD;} void Out(){for(int i=1;i<=n;++i) cout<<a[i]<<' '; cout<<endl;} int main(){ ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr); cin>>n; n=1<<n; for(int i=1;i<=n;++i) cin>>ca[i]; for(int i=1;i<=n;++i) cin>>cb[i]; Cp(),Fmt(a+1,Or),Fmt(b+1,Or),Mrg(),Fmt(a+1,[](int &a,int &b){b=Sub(b,a);}),Out(); Cp(),Fmt(a+1,And),Fmt(b+1,And),Mrg(),Fmt(a+1,[](int &a,int &b){a=Sub(a,b);}),Out(); Cp(),Fmt(a+1,Xor),Fmt(b+1,Xor),Mrg(),Fmt(a+1,[](int &a,int &b){int t=a; a=1ll*(a+b)*Inv%MOD,b=1ll*(t-b+MOD)*Inv%MOD;}),Out(); }
但只会这个还不够,你还要会写子集卷积。
求
你发现这个相较于 OR 卷积多出了一个
发现
所以如果我们每次只考虑大小为
所以对每一个
Code
#include<bits/stdc++.h> using namespace std; using llt=long long; using llf=long double; using ull=unsigned long long; #define endl '\n' #ifdef LOCAL FILE *InFile=freopen("in_out/in.in","r",stdin),*OutFile=freopen("in_out/out.out","w",stdout); #else FILE *InFile=stdin,*OutFile=stdout; #endif const int N=1<<20|3,MOD=1e9+9,Inv=(MOD+1)/2; int Add(int a,int b){return (a+=b)>=MOD?a-MOD:a;} int Sub(int a,int b){return (a-=b)<0?a+MOD:a;} int n,ca[23][N],cb[23][N],aas[23][N]; void Fmt(int *f,const function<void(int &,int &)> &T){for(int i=0;i<n;++i) for(int j=0;j<1<<n;++j) if(j>>i&1) T(f[j^1<<i],f[j]);} const function<void(int &,int &)> Or=[](int &a,int &b){b=Add(a,b);},IOr=[](int &a,int &b){b=Sub(b,a);}; int main(){ ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr); cin>>n; for(int i=0;i<1<<n;++i) cin>>ca[__builtin_popcount(i)][i]; for(int i=0;i<1<<n;++i) cin>>cb[__builtin_popcount(i)][i]; for(int i=0;i<=n;++i) Fmt(ca[i],Or),Fmt(cb[i],Or); for(int i=0;i<=n;++i) for(int j=0;j<=i;++j) for(int s=0;s<1<<n;++s) aas[i][s]=Add(aas[i][s],1ll*ca[j][s]*cb[i-j][s]%MOD); for(int i=0;i<=n;++i) Fmt(aas[i],IOr); for(int i=0;i<1<<n;++i) cout<<aas[__builtin_popcount(i)][i]<<' '; }
FWT
其实 FWT 和 FMT 本质是一个东西,它们俩变换出来的多项式都一模一样。
上次也说了,FWT 是基于变换的思想实现的,和 FFT 更相似,也更难写,所以学这个不是为了写板子的,其实是在学一些性质和构造本质的东西。
可以先去模板题的题解看一下板子。
容易发现,这个东西是线性变换,所以有
以下的
我们设,对于第
容易发现,对于 OR 卷积,
知道了上面的,来做好题:CF1119H Triple
solution
首先暴力卷积是显然的,考虑以
发现只有三个位置有值,对于每个的莫变可以暴力乘上贡献次数,这样的复杂度是
发现最后的卷积数组
后面的取值只有
考虑将
考虑设
发现
对于
解方程即可,最后做一遍 IFMT 即可,复杂度
Code
#include<bits/stdc++.h> using namespace std; using llt=long long; using llf=long double; using ull=unsigned long long; #define endl '\n' #ifdef LOCAL FILE *InFile=freopen("in_out/in.in","r",stdin),*OutFile=freopen("in_out/out.out","w",stdout); #else FILE *InFile=stdin,*OutFile=stdout; #endif const int N=2e5+3,MOD=998244353,Inv=(MOD+1)/2; int n,m,x,y,z,p1[N],p2[N],p3[N],aas[N],sa; int Fpw(int a,int b){ int ans=1; while(b){ if(b&1) ans=1ll*a*ans%MOD; a=1ll*a*a%MOD,b>>=1; } return ans; } void Fmt(int *f,const function<void(int &,int &)> &F){for(int i=1;i<m;i<<=1) for(int j=0;j<m;++j) if(j&i) F(f[j^i],f[j]);} const auto Xor=[](int &a,int &b){int t=a; a=(a+b)%MOD,b=(t-b)%MOD;}; const auto IXr=[](int &a,int &b){int t=a; a=1ll*(a+b)*Inv%MOD,b=1ll*(t-b)*Inv%MOD;}; int main(){ ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr); cin>>n>>m>>x>>y>>z,m=1<<m; for(int i=1;i<=n;++i){int a,b,c; cin>>a>>b>>c; sa^=a,b^=a,c^=a,++p1[b],++p2[c],++p3[b^c];} Fmt(p1,Xor),Fmt(p2,Xor),Fmt(p3,Xor); int s1=(1ll*x+y+z)%MOD,s2=(1ll*x+y-z)%MOD,s3=(1ll*x-y+z)%MOD,s4=(1ll*x-y-z)%MOD; for(int i=0;i<m;++i){ int c1=(1ll*n+p1[i]+p2[i]+p3[i])/4, c2=(1ll*n+p1[i]-c1-c1)/2, c3=(1ll*n+p2[i]-c1-c1)/2, c4=(1ll*n+p3[i]-c1-c1)/2; aas[i]=1ll*Fpw(s1,c1)*Fpw(s2,c2)%MOD*Fpw(s3,c3)%MOD*Fpw(s4,c4)%MOD; } Fmt(aas,IXr); for(int i=0;i<m;++i) cout<<(aas[i^sa]+MOD)%MOD<<' '; }
扩展到 进制
对于取
P
本文来自博客园,作者:5k_sync_closer,转载请注明原文链接:https://www.cnblogs.com/xrlong/p/18534992
版权声明:本作品采用 「署名-非商业性使用-相同方式共享 4.0 国际」许可协议(CC BY-NC-SA 4.0) 进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了