1. 程式人生 > >bzoj 5020: [THUWC 2017]在美妙的數學王國中暢遊【泰勒展開+LCT】

bzoj 5020: [THUWC 2017]在美妙的數學王國中暢遊【泰勒展開+LCT】

泰勒展開 clas iostream 公式 memset += cst print urn

參考:https://www.cnblogs.com/CQzhangyu/p/7500328.html
……其實理解了泰勒展開之後就是水題呢可是我還是用了兩天時間來搞懂啊
泰勒展開是到正無窮的,但是因為精度問題,所以一般展開十幾項就可以(這裏展開了17項)。以下是公式:
\[ e^x=\sum_{i=0}^{\infty}\frac{x^i}{i!} \]
\[ sin(x)=\sum_{i=0}^{\infty}\frac{(-1)^ix^{2i+1}}{(2i+1)!} \]
然後用二項式定理把x替換成ax+b:
\[ e^{ax+b}=\sum_{i=0}^{\infty}\frac{\sum_{j=0}^{i}C_i^ja^jx^jb^{i-j}}{i!} \]


\[ sin(ax+b)=\sum_{i=0}^{\infty}\frac{(-1)^i\sum_{j=0}^{2i+1}C_i^ja^jx^jb^{2i+1-j}}{(2i+1)!} \]
展開的17項在splay上可以直接逐項加起來,然後計算答案的時候直接乘相應的x次方即可。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=1000005,D=17;
int n,m,tp[N],st[N],top;
double a[N],b[N],jc[20
],y[20][20],at[20],bt[20]; char s[100]; struct qwe { int f,c[2],sz,lz,tp; double v[20],s[20],a,b; void tl() { int i,j,f; memset(v,0,sizeof(v)); if(tp==1) { for(at[0]=bt[0]=1,i=1;i<=D;i++) at[i]=at[i-1]*a,bt[i]=bt[i-1]*b; for
(i=1;i<=D;i+=2) { f=(i%4==1)?1:-1; for(j=0;j<=i;j++) v[j]+=f*at[j]*bt[i-j]*y[i][j]/jc[i]; } } else if(tp==2)//這裏枚舉的是2i+1 { for(at[0]=bt[0]=1,i=1;i<=D;i++) at[i]=at[i-1]*a,bt[i]=bt[i-1]*b; for(i=0;i<=D;i++) for(j=0;j<=i;j++) v[j]+=at[j]*bt[i-j]*y[i][j]/jc[i]; } else v[0]=b,v[1]=a; } }t[N]; int read() { int r=0,f=1; char p=getchar(); while(p>‘9‘||p<‘0‘) { if(p==‘-‘) f=-1; p=getchar(); } while(p>=‘0‘&&p<=‘9‘) { r=r*10+p-48; p=getchar(); } return r*f; } bool srt(int x) { return t[t[x].f].c[0]!=x&&t[t[x].f].c[1]!=x; } void ud(int x) { for(int i=0;i<=D;i++) t[x].s[i]=t[t[x].c[0]].s[i]+t[t[x].c[1]].s[i]+t[x].v[i]; t[x].sz=t[t[x].c[0]].sz+t[t[x].c[1]].sz+1; } void pd(int x) { if(t[x].lz) { t[x].lz=0; t[t[x].c[0]].lz^=1; t[t[x].c[1]].lz^=1; swap(t[x].c[0],t[x].c[1]); } } void updata(int x) { if(!srt(x)) updata(t[x].f); pd(x); } void zhuan(int x) { int l,r,y=t[x].f,z=t[y].f; if(t[y].c[0]==x) l=0; else l=1; r=l^1; if(!srt(y)) { if(t[z].c[0]==y) t[z].c[0]=x; else t[z].c[1]=x; } t[x].f=z;t[y].f=x; t[t[x].c[r]].f=y; t[y].c[l]=t[x].c[r]; t[x].c[r]=y; ud(y);// ud(x); } void splay(int x) {//cout<<"splay"<<x<<endl; top=0; st[++top]=x; for(int i=x;!srt(i);i=t[i].f) st[++top]=t[i].f; while(top) pd(st[top--]); while(!srt(x)) { int y=t[x].f,z=t[y].f; if(!srt(y)) { if((t[y].c[0]==x)^(t[z].c[0]==y)) zhuan(x); // else // zhuan(y); } zhuan(x); } ud(x); } void acc(int x) {//cout<<"acc"<<x<<endl; for(int i=0;x;i=x,x=t[x].f) {//cout<<"foracc"<<x<<endl; splay(x); t[x].c[1]=i; ud(x); } } int zhao(int x) { while(t[x].f) x=t[x].f; return x; acc(x); } void mkrt(int x) { acc(x); splay(x); t[x].lz^=1; } void lk(int x,int y) { mkrt(x); t[x].f=y; } void ct(int x,int y) {//cout<<x<<" "<<y<<endl; mkrt(x); acc(y); splay(y); if(t[y].c[0]!=x) return; t[x].f=0; t[y].c[0]=0; ud(y); } int main() { // n=read(),m=read(); scanf("%d%d%s",&n,&m,s); jc[0]=1; for(int i=1;i<=D;i++) jc[i]=jc[i-1]*i; y[0][0]=1; for(int i=1;i<=D;i++) { y[i][0]=1; for(int j=1;j<=D;j++) y[i][j]=y[i-1][j-1]+y[i-1][j]; } for(int i=1;i<=n;i++) { // t[i].tp=read(); scanf("%d%lf%lf",&t[i].tp,&t[i].a,&t[i].b); t[i].tl(); ud(i); } while(m--) { scanf("%s",s); if(s[0]==‘a‘) { // int a=read()+1,b=read()+1; int a,b; scanf("%d%d",&a,&b); lk(a+1,b+1); } else if(s[0]==‘d‘) { // int a=read()+1,b=read()+1; int a,b; scanf("%d%d",&a,&b); ct(a+1,b+1); } else if(s[0]==‘m‘) { // int a=read()+1; int a; scanf("%d",&a); a++; splay(a); // t[a].tp=read(); scanf("%d%lf%lf",&t[a].tp,&t[a].a,&t[a].b); t[a].tl(); ud(a); } else { // int a=read()+1,b=read()+1; int a,b; double x,y,ans; scanf("%d%d%lf",&a,&b,&x); a++,b++; if(zhao(a)!=zhao(b)) { puts("unreachable"); continue; } y=1,ans=0; mkrt(a); acc(b); splay(b); for(int j=0;j<=D;j++,y*=x) ans+=y*t[b].s[j]; printf("%.8le\n",ans); } } return 0; }

bzoj 5020: [THUWC 2017]在美妙的數學王國中暢遊【泰勒展開+LCT】