1. 程式人生 > >BZOJ5020: [THUWC 2017]在美妙的數學王國中暢遊(LCT,泰勒展開,二項式定理)

BZOJ5020: [THUWC 2017]在美妙的數學王國中暢遊(LCT,泰勒展開,二項式定理)

Description

數字和數學規律主宰著這個世界。   機器的運轉,   生命的消長,   宇宙的程序,   這些神祕而又美妙的過程無不可以用數學的語言展現出來。   這印證了一句古老的名言:   “學好數理化,走遍天下都不怕。”   學渣小R被大學的數學課程虐得生活不能自理,微積分的成績曾是他在教室裡上的課的最低分。然而他的某位陳姓室友卻能輕鬆地在數學考試中得到滿分。為了提升自己的數學課成績,有一天晚上(在他睡覺的時候),他來到了數學王國。
  數學王國中,每個人的智商可以用一個屬於 [0,1]的實數表示。數學王國中有 n 個城市,編號從 0 到 n−1 ,這些城市由若干座魔法橋連線。每個城市的中心都有一個魔法球,每個魔法球中藏有一道數學題。每個人在做完這道數學題之後都會得到一個在 [0,1] 區間內的分數。一道題可以用一個從 [0,1] 對映到 [0,1]的函式 f(x) 表示。若一個人的智商為 x ,則他做完這道數學題之後會得到 f(x)分。函式 f有三種形式:       正弦函式 sin(ax+b) (a∈[0,1],b∈[0,π],a+b∈[0,π])
      指數函式 e^(ax+b) (a∈[−1,1],b∈[−2,0],a+b∈[−2,0])       一次函式 ax+b (a∈[−1,1],b∈[0,1],a+b∈[0,1] 數學王國中的魔法橋會發生變化,有時會有一座魔法橋消失,有時會有一座魔法橋出現。但在任意時刻,只存在至多一條連線任意兩個城市的簡單路徑(即所有城市形成一個森林)。在初始情況下,數學王國中不存在任何的魔法橋。 數學王國的國王拉格朗日很樂意傳授小R數學知識,但前提是小R要先回答國王的問題。這些問題具有相同的形式,即一個智商為 x 的人從城市 u 旅行到城市 v(即經過 u 到 v 這條路徑上的所有城市,包括 u和 v )且做了所有城市內的數學題後,他所有得分的總和是多少。

 

Input

第一行兩個正整數 n,m 和一個字串 type 。 表示數學王國中共有 n 座城市,發生了 m 個事件,該資料的型別為 type 。  typet 字串是為了能讓大家更方便地獲得部分分,你可能不需要用到這個輸入。 其具體含義在【資料範圍與提示】中有解釋。   接下來 n 行,第 i 行表示初始情況下編號為 i 的城市的魔法球中的函式。 一個魔法用一個整數 f表示函式的型別,兩個實數 a,b 表示函式的引數,若     f=1,則函式為 f(x)=sin(ax+b)(a∈[0,1],b∈[0,π],a+b∈[0,π])     f=2,則函式為 f(x)=e^(ax+b)(a∈[−1,1],b∈[−2,0],a+b∈[−2,0])     f=3,則函式為 f(x)=ax+b(a∈[−1,1],b∈[0,1],a+b∈[0,1]) 接下來 m行,每行描述一個事件,事件分為四類。     appear u v 表示數學王國中出現了一條連線 u 和 v 這兩座城市的魔法橋 (0≤u,v<n,u≠v) ,保證連線前 u和 v 這兩座城市不能互相到達。     disappear u v 表示數學王國中連線 u 和 v 這兩座城市的魔法橋消失了,保證這座魔法橋是存在的。     magic c f a b 表示城市 c 的魔法球中的魔法變成了型別為 f ,引數為 a,b 的函式     travel u v x 表示詢問一個智商為 x 的人從城市 u 旅行到城市 v  (即經過 u到 v 這條路徑上的所有城市,包括 u 和 v )後,他得分的總和是多少。  若無法從 u 到達 v ,則輸出一行一個字串 unreachable。 1≤n≤100000,1≤m≤200000

 

Output

對於每個詢問,輸出一行實數,表示得分的總和。

 

Sample Input

3 7 C1
1 1 0
3 0.5 0.5
3 -0.5 0.7
appear 0 1
travel 0 1 0.3
appear 0 2
travel 1 2 0.5
disappear 0 1
appear 1 2
travel 1 2 0.5

Sample Output

9.45520207e-001
1.67942554e+000
1.20000000e+000

解題思路:

題目描述如此毒瘤。

從操作3得到的啟發,將多項式展開對應項相加。

這道題可以將sin(ax+b),eax+b泰勒展開。

精度的話16位肯定夠。剩下的就是裸的LCT了。

聽黴黴的歌寫泰勒展開不容易錯

程式碼:

 

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #define lll tr[spc].ch[0]
  5 #define rrr tr[spc].ch[1]
  6 #define ls ch[0]
  7 #define rs ch[1]
  8 const int N=100010;
  9 const int oo=16;
 10 struct trnt{
 11     int ch[2];
 12     int fa;
 13     int lzt;
 14     int type;
 15     bool anc;
 16     double a,b;
 17     double C[oo];
 18     double f[oo];
 19     double val(double x)
 20     {
 21         double ans=f[0];
 22         double t=x;
 23         for(int i=1;i<oo;i++,t*=x)
 24             ans+=f[i]*t;
 25         return ans;
 26     }
 27     void Insert(void)
 28     {
 29         scanf("%d",&type);
 30         scanf("%lf%lf",&a,&b);
 31         return ;
 32     }
 33     void Taylor(double *fac)
 34     {
 35         double at[oo],bt[oo];
 36         for(int i=0;i<oo;i++)
 37             C[i]=at[i]=bt[i]=0;
 38         at[0]=1;
 39         bt[0]=1;
 40         for(int i=1;i<oo;i++)
 41             at[i]=at[i-1]*a,bt[i]=bt[i-1]*b;
 42         if(type==1)
 43         {//sin(ax+b)
 44             double tmp=1;
 45             for(int i=1;i<oo;i+=2)
 46             {
 47                 for(int j=0;j<=i;j++)
 48                     C[j]+=tmp*at[j]*bt[i-j]/fac[j]/fac[i-j];
 49                 tmp*=-1.00;
 50             }
 51             return ;
 52         }
 53         if(type==2)
 54         {//e^(ax+b)
 55             for(int i=0;i<oo;i++)
 56             {
 57                 for(int j=0;j<=i;j++)
 58                     C[j]+=fac[i]/fac[j]/fac[i-j]*at[j]*bt[i-j]/fac[i];
 59             }
 60             return ;
 61         }
 62         if(type==3)
 63         {
 64             C[0]=b;
 65             C[1]=a;
 66             return ;
 67         }
 68     }
 69 }tr[N];
 70 int n,m;
 71 double fac[50];
 72 char tmp[10000];
 73 bool whc(int spc)
 74 {
 75     return tr[tr[spc].fa].rs==spc;
 76 }
 77 void pushup(int spc)
 78 {
 79     for(int i=0;i<oo;i++)
 80         tr[spc].f[i]=tr[spc].C[i];
 81     if(lll)
 82         for(int i=0;i<oo;i++)
 83             tr[spc].f[i]+=tr[lll].f[i];
 84     if(rrr)
 85         for(int i=0;i<oo;i++)
 86             tr[spc].f[i]+=tr[rrr].f[i];
 87     return ;
 88 }
 89 void trr(int spc)
 90 {
 91     if(!spc)
 92         return ;
 93     std::swap(lll,rrr);
 94     tr[spc].lzt^=1;
 95     return ;
 96 }
 97 void pushdown(int spc)
 98 {
 99     if(tr[spc].lzt)
100     {
101         trr(lll);
102         trr(rrr);
103         tr[spc].lzt=0;
104     }
105     return ;
106 }
107 void recal(int spc)
108 {
109     if(!tr[spc].anc)
110         recal(tr[spc].fa);
111     pushdown(spc);
112     return ;
113 }
114 void rotate(int spc)
115 {
116     int f=tr[spc].fa;
117     bool k=whc(spc);
118     tr[f].ch[k]=tr[spc].ch[!k];
119     tr[spc].ch[!k]=f;
120     if(tr[f].anc)
121     {
122         tr[f].anc=0;
123         tr[spc].anc=1;
124     }else
125         tr[tr[f].fa].ch[whc(f)]=spc;
126     tr[spc].fa=tr[f].fa;
127     tr[f].fa=spc;
128     tr[tr[f].ch[k]].fa=f;
129     pushup(f);
130     pushup(spc);
131     return ;
132 }
133 void splay(int spc)
134 {
135     recal(spc);
136     while(!tr[spc].anc)
137     {
138         int f=tr[spc].fa;
139         if(tr[f].anc)
140         {
141             rotate(spc);
142             return ;
143         }
144         if(whc(spc)^whc(f))
145             rotate(spc);
146         else
147             rotate(f);
148         rotate(spc);
149     }
150     return ;
151 }
152 void access(int spc)
153 {
154     int lst=0;
155     while(spc)
156     {
157         splay(spc);
158         tr[rrr].anc=1;
159         tr[lst].anc=0;
160         rrr=lst;
161         lst=spc;
162         pushup(spc);
163         spc=tr[spc].fa;
164     }
165     return ;
166 }
167 void Mtr(int spc)
168 {
169     access(spc);
170     splay(spc);
171     trr(spc);
172     return ;
173 }
174 void split(int x,int y)
175 {
176     Mtr(x);
177     access(y);
178     splay(y);
179     return ;
180 }
181 void link(int x,int y)
182 {
183     Mtr(x);
184     tr[x].fa=y;
185     return ;
186 }
187 bool together(int x,int y)
188 {
189     split(x,y);
190     while(tr[y].ls)
191         y=tr[y].ls;
192     return x==y;
193 }
194 void cut(int x,int y)
195 {
196     split(x,y);
197     tr[x].fa=0;
198     tr[x].anc=true;
199     tr[y].ls=0;
200     pushup(y);
201     return ;
202 }
203 int main()
204 {
205     scanf("%d%d",&n,&m);
206     scanf("%s",tmp);
207     fac[0]=1;
208     for(int i=1;i<oo;i++)
209     {
210         double x=i;
211         fac[i]=fac[i-1]*x;
212     }
213     for(int i=1;i<=n;i++)
214     {
215         tr[i].Insert();
216         tr[i].Taylor(fac);
217         tr[i].anc=1;
218     }
219     while(m--)
220     {
221         scanf("%s",tmp+1);
222         if(tmp[1]=='a')
223         {
224             int a,b;
225             scanf("%d%d",&a,&b);
226             a++,b++;
227             link(a,b);
228         }else if(tmp[1]=='d')
229         {
230             int a,b;
231             scanf("%d%d",&a,&b);
232             a++,b++;
233             cut(a,b);
234         }else if(tmp[1]=='m')
235         {
236             int x;
237             scanf("%d",&x);
238             x++;
239             splay(x);
240             tr[x].Insert();
241             tr[x].Taylor(fac);
242         }else{
243             int a,b;
244             scanf("%d%d",&a,&b);
245             double x;
246             scanf("%lf",&x);
247             a++,b++;
248             if(!together(a,b))
249                 puts("unreachable");
250             else{
251                 double ret=tr[b].val(x);
252                 printf("%.8e\n",ret);
253             }
254         }
255     }
256     return 0;
257 }