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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

[CQOI2018]九连环

發布時間:2024/1/1 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [CQOI2018]九连环 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、題目

點此看題

二、解法

根據題目中444連環的解釋,你可以發現拆除444連環滿足如下規律:

  • 拆掉一個222連環,使得原環變成110011001100
  • 拿掉最左邊的111
  • 加二連環使其變為011101110111
  • 拆三連環

這就完成了一個問題的轉化,由于拆和加環效果相同,我們定義dpidp_idpi?為拆掉iii連環需要的步數,則有遞推式:
dp[i]=2?dp[i?2]+dp[i?1]+1dp[i]=2\cdot dp[i-2]+dp[i-1]+1dp[i]=2?dp[i?2]+dp[i?1]+1可以把答案寫成二進制的形式:1 10 101 1010 10101 ..................

可以發現相鄰兩個二進制數的和是1111..1111..1111..的形式,所以 dp[i]+dp[i+1]=2i+1dp[i]+dp[i+1]=2^{i+1}dp[i]+dp[i+1]=2i+1,結合dp[n]=2dp[n?1]+(n&1)?1:0dp[n]=2dp[n?1]+(n\&1)?1:0dp[n]=2dp[n?1]+(n&1)?1:0(打表規律),可以發現答案是2i+13\frac{2^{i+1}}{3}32i+1?

這樣問題就轉化成了高精度,可以用FFT\text{FFT}FFT優化,下面寫出一些注意事項:

  • 清零最重要,每個地方每個數組及時清零
  • 不要把數組開在函數里面,開在函數外面反復利用
#include <cstdio> #include <vector> #include <cstring> #include <cmath> using namespace std; const int MAXN = 100005; const double pi = acos(-1.0); int read() {int num=0,flag=1;char c;while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;while(c>='0'&&c<='9')num=(num<<3)+(num<<1)+(c^48),c=getchar();return num*flag; } int n,T; struct complex {double x,y;complex() {x=y=0;}complex(double X,double Y) : x(X) , y(Y) {}complex operator + (const complex &R) const {return complex(x+R.x,y+R.y);}complex operator - (const complex &R) const {return complex(x-R.x,y-R.y);}complex operator * (const complex &R) const {return complex(x*R.x-y*R.y,x*R.y+y*R.x);} }A[MAXN],B[MAXN]; void FFT(int len,complex *a,int flg) {if(len==1) return ;complex a1[len>>1],a2[len>>1];for(int i=0;i<len;i+=2) a1[i>>1]=a[i],a2[i>>1]=a[i+1];FFT(len>>1,a1,flg);FFT(len>>1,a2,flg);const complex w=complex(cos(pi*2.0/len),sin(pi*2.0/len)*flg);complex k=complex(1,0);len>>=1;for(int i=0;i<len;i++,k=k*w){a[i]=a1[i]+k*a2[i];a[i+len]=a1[i]-k*a2[i];} } struct bignum {int n,a[MAXN];bignum() {memset(a,0,sizeof a);n=1;}bignum(int x){memset(a,0,sizeof a);n=0;if(!x) {n=1;return ;}while(x) a[n++]=x%10,x/=10;}void print(){for(int i=n-1;i>=0;i--)printf("%d",a[i]);puts("");}void operator /= (int x){int t=0,len=0;for(int i=n-1;i>=0;i--){t=t*10+a[i];a[i]=t/x;t%=x;if(!len && a[i]) len=i+1;}n=max(len,1);}void operator *= (bignum b){int len=1;while(len<=n+b.n) len<<=1;for(int i=0;i<len;i++) A[i]=B[i]=complex(0,0);for(int i=0;i<n;i++) A[i]=complex(a[i],0);for(int i=0;i<b.n;i++) B[i]=complex(b.a[i],0);FFT(len,A,1);FFT(len,B,1);for(int i=0;i<len;i++) A[i]=A[i]*B[i];FFT(len,A,-1);for(int i=0;i<n+b.n;i++)a[i]=0;for(int i=0;i<n+b.n;i++){a[i]+=(int)(A[i].x/len+0.5);if(a[i]>=10)a[i+1]+=a[i]/10,a[i]%=10;}for(int i=n+b.n-1;i>=0;i--)if(a[i]){n=i+1;break;}} }a,r; int main() {T=read();while(T--){n=read()+1;a=bignum(2),r=bignum(1);while(n>0){if(n&1) r*=a;a*=a;n>>=1;}r/=3;r.print();} }

總結

以上是生活随笔為你收集整理的[CQOI2018]九连环的全部內容,希望文章能夠幫你解決所遇到的問題。

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