日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

多项式乘法:练习总结

發布時間:2023/12/3 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 多项式乘法:练习总结 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 前言
    • 代碼
  • 禮物
    • 代碼
  • 差分和前綴和
    • 代碼
  • 開拓者的知識
    • 代碼
  • 總結

前言

這兩天由于國慶集訓全是陰間的生成函數,所以就學了一點點相關的內容
其實就學了個FFT和NTT
也算是點開了一個小小的技能點吧
進入多項式才發現里面世界的廣闊
然而由于這玩意沒有一個是NOIP考點,而且似乎對于提高級的題目解決不會有太大的輔助作用 (不像某些神仙的數據結構) 所以覺得后面的先放放吧
但是這幾天多項式也水了四紫兩藍嘛awa

入門題
裸且簡單
但是我當時實在是根本沒明白多項式是啥
所以還是看了題解
…不丟人!(理直氣壯)
一個技巧是把函數翻轉
但這本身甚至幾乎不配叫做技巧
qwq

代碼

#include<bits/stdc++.h> using namespace std; #define ll long long #define il inline const int N=1e6+100; const int M=150; const int mod=998244353; const double pi=acos(-1.0); inline ll read(){ll x=0,f=1;char c=getchar();while(!isdigit(c)){if(c=='-') f=-1;c=getchar();}while(isdigit(c)){x=x*10+c-'0';c=getchar();}return x*f; } int n,m,lim,k; struct node{double x,y;node(double a=0,double b=0){x=a;y=b;} }A[N],B[N],C[N]; il node operator * (node a,node b){return (node){a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x}; } il node operator + (node a,node b){return (node){a.x+b.x,a.y+b.y}; } il node operator - (node a,node b){return (node){a.x-b.x,a.y-b.y}; } int r[N]; il void fft(node *x,int lim,int flag){for(int i=0;i<=lim;i++){if(i<r[i]) swap(x[i],x[r[i]]);}for(int l=1;l<lim;l<<=1){node o(cos(pi/l),flag*sin(pi/l));for(int st=0;st<=lim;st+=l<<1){node t(1,0);for(int j=0;j<l;j++,t=t*o){node u=x[st+j],v=t*x[st+j+l];x[st+j]=u+v;x[st+j+l]=u-v;}}}return; } int main(){n=read();for(int i=1;i<=n;i++){scanf("%lf",&A[i].x);B[i].x=(double)(1.0/i/i);C[n-i].x=A[i].x;}int L=0,lim=1;while(lim<=n<<1){lim<<=1;L++;}for(int i=1;i<=lim;i++) r[i]=(r[i>>1]>>1)|((i&1)<<(L-1));fft(A,lim,1);fft(B,lim,1);fft(C,lim,1);for(int i=0;i<=lim;i++){A[i]=A[i]*B[i];C[i]=C[i]*B[i];}fft(A,lim,-1);fft(C,lim,-1);for(int i=1;i<=n;i++) printf("%lf\n",(A[i].x-C[n-i].x)/lim);return 0; } /**/

禮物

這個題是自己做的
顯然要把平方拆開
然后發現加上的亮度是可以O1算的
然后是變成最小化一個奇怪的東西
由于循環的性質倍長一下即可

代碼

#include<bits/stdc++.h> using namespace std; #define ll long long #define il inline const int N=2e6+100; const double pi=acos(-1.0); ll read(){ll x=0,f=1;char c=getchar();while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}while(isdigit(c)){x=x*10+c-'0';c=getchar();}return x*f; } int n,m; struct node{double x,y;node (double a=0,double b=0){x=a;y=b;} }A[N],B[N]; il node operator *(node a,node b){return (node){a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x}; } il node operator +(node a,node b){return (node){a.x+b.x,a.y+b.y}; } il node operator -(node a,node b){return (node){a.x-b.x,a.y-b.y}; } int r[N]; il void fft(node *x,int lim,int flag){for(int i=1;i<lim;i++){if(i<r[i]) swap(x[i],x[r[i]]);}for(int l=1;l<lim;l<<=1){node o(cos(pi/l),flag*sin(pi/l));for(int st=0;st<lim;st+=l<<1){node t(1,0);for(int i=0;i<l;i++,t=t*o){node u=x[st+i],v=t*x[st+l+i];x[st+i]=u+v;x[st+l+i]=u-v;}}} } ll x[N],y[N],tot,Sx,Sy,ans=2e18; int main(){n=read();m=read();for(int i=1;i<=n;i++) x[i]=read();for(int i=1;i<=n;i++) y[i]=read();for(int i=1;i<=n;i++){tot+=x[i]*x[i]+y[i]*y[i];Sx+=x[i];Sy+=y[i];}if(Sy<Sx) swap(Sy,Sx);ll a=(Sy-Sx)/n,b=a+1;if(a*a*n+2*a*(Sx-Sy)>b*b*n+2*b*(Sx-Sy)) swap(a,b);tot+=a*a*n+2*a*(Sx-Sy);//printf("a=%d\n",a);for(int i=1;i<=n;i++){A[i].x=x[i];B[n+n-i].x=B[n-i].x=y[i];}int lim=1,L=0;while(lim<3*n+2){lim<<=1;L++;}for(int i=1;i<lim;i++) r[i]=(r[i>>1]>>1)|((i&1)<<(L-1));fft(A,lim,1);fft(B,lim,1);for(int i=0;i<lim;i++) A[i]=A[i]*B[i];fft(A,lim,-1);for(int i=0;i<n;i++){ll now=(ll)(A[n-i+n].x/lim+0.5);ans=min(ans,tot-2*now);}printf("%lld\n",ans); }

差分和前綴和

看起來完全的裸題然鵝我就是不會
本題的一個關鍵思想是卷積滿足結合律
所以你只要把k=1的柿子找到無腦k次方即可
前綴和和模擬考試的式子一模一樣
主要是卡在了差分
就是卷了一個1?x1-x1?x
其實不必“發現”,可以生成函數很方便的求出來
然后k次方二項式就像喝水一樣了

代碼

#include<bits/stdc++.h> using namespace std; #define ll long long const int N=1e6+100; const int mod= 1004535809; #define il inline inline ll read(){ll x=0,f=1;char c=getchar();while(!isdigit(c)){if(c=='-') f=-1;c=getchar();}while(isdigit(c)){x=x*10+c-'0';c=getchar();x%=mod;}return x*f; } ll n,k; ll A[N],B[N],r[N],lim,L; ll ksm(ll x,ll k){ll res=1;while(k){if(k&1) res=res*x%mod;x=x*x%mod;k>>=1;}return res; } void ntt(ll *x,int flag){for(int i=0;i<lim;i++){if(i<r[i]) swap(x[i],x[r[i]]);}for(int l=1;l<lim;l<<=1){ll t0=ksm(3,(mod-1)/(l<<1));if(flag==-1) t0=ksm(t0,mod-2);for(int st=0;st<lim;st+=l<<1){ll t=1;for(int i=0;i<l;i++,t=t*t0%mod){ll u=x[st+i],v=t*x[st+i+l]%mod;x[st+i]=(u+v)%mod;x[st+i+l]=(u-v+mod)%mod;}}}if(flag==-1){ll ni=ksm(lim,mod-2);for(int i=0;i<lim;i++) x[i]=x[i]*ni%mod;} } int main(){n=read();k=read();int op=read();for(int i=1;i<=n;i++) A[i]=read();if(op==0){B[0]=1;for(int i=1;i<=n;i++){B[i]=B[i-1]*(k+i-1)%mod*ksm(i,mod-2)%mod;//printf("i=%d %lld\n",i,B[i]);}}else{//B[0]=k%2?-1:1;B[0]=1;for(int i=1;i<=n;i++){B[i]=-1*B[i-1]*(k-i+1)%mod*ksm(i,mod-2)%mod;//B[i]=(B[i]+mod)%mod;//printf("i=%d %lld\n",i,B[i]);}for(int i=0;i<=n;i++) B[i]=(B[i]+mod)%mod;}lim=1;while(lim<n+n+1) lim<<=1,L++;for(int i=1;i<lim;i++) r[i]=(r[i>>1]>>1)|((i&1)<<(L-1));ntt(A,1);ntt(B,1);for(int i=0;i<lim;i++) A[i]=A[i]*B[i]%mod;ntt(A,-1);for(int i=1;i<=n;i++) printf("%lld ",A[i]);return 0; } /* 3 1 1 1 1 1 */

開拓者的知識

題面的圖好可愛丫!
雖然還是不太難,但對于剛入門的我而言,也可以作為一道暫時的畢業題了
我的做法:

  • 瞪眼觀察(失敗)
  • 暴力打表
  • 尋找規律
  • 卷積
  • tmd模數用的樓上那題的1004535809忘改了WA了3次
  • AC
  • 打表真香
    但是我們還是要給那個通項一個來頭
    我是根本沒有理解這個柿子的性質
    關鍵性質:sum往上遞歸時,區間只會減小不會增大
    挺顯然的
    那么考慮對于一個固定的rrr,aia_iai?會對其產生多少貢獻
    顯然就是你取k個端點不能往外移,且最終(也就是每個)區間都包含i的方案數
    這玩意其實就是(1,i)選可重的k個做左端點,(i,r)選可重的k個做右端點
    經典的可重復放置的計數
    就可以辣

    代碼

    #include<bits/stdc++.h> using namespace std; #define ll long long const int N=1e6+100; const int mod= 1004535809; #define il inline inline ll read(){ll x=0,f=1;char c=getchar();while(!isdigit(c)){if(c=='-') f=-1;c=getchar();}while(isdigit(c)){x=x*10+c-'0';c=getchar();}return x*f; } ll n,k; ll A[N],B[N],r[N],lim,L; ll ksm(ll x,ll k){ll res=1;while(k){if(k&1) res=res*x%mod;x=x*x%mod;k>>=1;}return res; } void ntt(ll *x,int flag){for(int i=0;i<lim;i++){if(i<r[i]) swap(x[i],x[r[i]]);}for(int l=1;l<lim;l<<=1){ll t0=ksm(3,(mod-1)/(l<<1));if(flag==-1) t0=ksm(t0,mod-2);for(int st=0;st<lim;st+=l<<1){ll t=1;for(int i=0;i<l;i++,t=t*t0%mod){ll u=x[st+i],v=t*x[st+i+l]%mod;x[st+i]=(u+v)%mod;x[st+i+l]=(u-v+mod)%mod;}}}if(flag==-1){ll ni=ksm(lim,mod-2);for(int i=0;i<lim;i++) x[i]=x[i]*ni%mod;} } ll f[N]; int main(){n=read();k=read();for(int i=1;i<=n;i++) A[i]=read()%mod;f[0]=1;for(int i=1;i<=n;i++) f[i]=f[i-1]*(k+i-1)%mod*ksm(i,mod-2)%mod;for(int i=1;i<=n;i++){A[i]=A[i]*f[i-1]%mod;}for(int i=0;i<=n;i++){B[i]=f[i];}lim=1;while(lim<n+n+2) lim<<=1,L++;for(int i=1;i<lim;i++) r[i]=(r[i>>1]>>1)|((i&1)<<(L-1));ntt(A,1);ntt(B,1);for(int i=0;i<lim;i++) A[i]=A[i]*B[i]%mod;ntt(A,-1);for(int i=1;i<=n;i++) printf("%lld ",A[i]);return 0; } /* 3 1 1 1 1 1 */

    總結

    說實話上道之后這些剛入門的多項式的題確實不算很難
    但多項式真的是路漫漫其修遠兮…
    我可能會noip之后開始系統的搞一搞吧
    那時候時間就充裕了
    現在還是要重點在提高級內容
    辣么,再見~

    創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

    總結

    以上是生活随笔為你收集整理的多项式乘法:练习总结的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。