在美妙的数学王国中畅游
https://www.zybuluo.com/ysner/note/1242005
題面
數學王國有\(n\)座城市(森林狀),每個城市有三個參數\(f,a,b\),當一個智商為\(x\)的人經過會得到\(f(x)\)的收益。
- \(f=1,f(x)=sin(ax+b)\)
- \(f=2,f(x)=e^{ax+b}\)
- \(f=3,f(x)=ax+b\)
有\(m\)個事件,分為\(4\)類:
1、建邊
2、斷邊
3、修改一個城市的參數
4、詢問一個智商為\(x\)的人,判斷是否聯通,若聯通則答從\(u\)到\(v\)的收益和。
(除最下一檔,各檔分互不包含)
- \(5pts\ n\leq100,m\leq200\)
- \(20pts\) 不存在\(2\)操作,\(u=v-1\),\(x=1\)
- \(5pts\) 不存在\(2\)操作,\(x=1\)
- \(10pts\) \(x=1\)
- \(30pts\) 不存在\(2\)操作,\(u=v-1\)
- \(100pts\) \(n\leq10^5,m\leq2*10^5\)
解析
“刪邊”這操作欽定使用\(LCT\)。于是一只不會lct的蒟蒻就gg啦
沒有人像我一樣在計算器上二分出\(e=2.718281828\)的吧。
\(5pts\)算法
我們可以用鄰接矩陣維護一條邊有沒有被刪掉。
暴力修改。
詢問收益就從\(u\)出發對全圖\(dfs\)。
復雜度\(O(mn^2)\)
\(5+20pts\)算法
不需要刪邊,判連通性就可以并查集了。
\(x=1\)代表可以\(O(n)\)預處理出每個城市收益。
詢問就是問一條鏈上的區間和。
用樹狀數組維護前綴和即可做到\(O(logn)\)查詢與修改。
總復雜度\(O(qlogn)\)
\(5+20+5pts\)算法
這是個森林,不太好搞出\(dfs\)序,于是應該只能上\(LCT\)。
\(5+20+5+10\)算法
怕是\(LCT\)模板。
\(5+20+30\)算法
注意到題目最下方有一個奇奇怪怪的公式。
那個玩意兒能夠方便地近似將\(f(x_0)\)轉化為\(f(x)\)。
題目中\(x=1\)這一條件顯然能給我們以啟迪。
如果我們一開始預處理所有的\(f(0)\),我們在詢問時就可以先得到\(\sum f(0)\),再在常數時間內將\(\sum f(0)\)轉化為答案\(\sum f(x)\)。
但是對一個不會求導的高一學生就很傷了:
\[(a^x)'=a^x*\ln a\]\[(e^x)'=e^x\]\[(a+b)'=a'+b'\]\[(ab)'=ab'+a'b\]\[(x^a)'=ax^{a-1}\]\[b'=0\](\(b\)為常數)
\[(\sin x)'=\cos x\]\[(\cos x)'=-\sin x\]\[(-\sin x)'=-\cos x\]\[(-\cos x)'=\sin x\]
(周期!)
對復合函數:\[[f(g(x))]'=g(x)'*f(g(x))'\]
代入這道題
對三角函數:
\[\sin'(ax+b)=a\sin(ax+b)\]\[\sin''(ax+b)=-a^2\sin(ax+b)\]\[\sin'''(ax+b)=-a^3\sin(ax+b)\]
對自然對數冪次方:\[(e^{ax+b})'=(ax+b)'*(e^{ax+b})'\]\[=((ax)'+b')*e^{ax+b}\]\[=a*e^{ax+b}\]
則\[(e^{ax+b})^{(n)}=a^ne^{ax+b}\]\((n)\)代表\(n\)階導數。
對一次函數:\[(ax+b)'=(ax)'+b'=ax'+a'x=a\]
于是代入公式即可得解。
\(100pts\)算法
用\(LCT\)維護信息。
#include<iostream> #include<cstring> #include<cmath> #include<cstdio> #include<cstdlib> #include<algorithm> #define ll long long #define re register #define il inline #define M 15 #define eps 1e-12 #define fp(i,a,b) for(re int i=a;i<=b;i++) #define fq(i,a,b) for(re int i=a;i>=b;i--) using namespace std; const int N=5e5+100; const double E=2.718281828; int n,m,f[N],ff[N],t[N][2],st[N]; bool r[N]; double a[N],b[N],ans,x,sum[20][N],jc[N],ssin[N],ccos[N]; char c[10],op[20]; il int gi() {re int x=0,t=1;re char ch=getchar();while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();if(ch=='-') t=-1,ch=getchar();while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();return x*t; } il double Sin(re int u,re double x) {if(ssin[u]>-eps&&ssin[u]<eps) return ssin[u]=sin(x);else return ssin[u]; } il double Cos(re int u,re double x) {if(ccos[u]>-eps&&ccos[u]<eps) return ccos[u]=cos(x);else return ccos[u]; } il bool isrt(re int u){return t[f[u]][0]==u||t[f[u]][1]==u;} il void pushup(re int u) {fp(i,0,M) sum[i][u]=sum[i][t[u][0]]+sum[i][t[u][1]];if(ff[u]==1){double tmp=1;fp(i,0,M){if(i%4==0) sum[i][u]+=Sin(u,b[u])*tmp;if(i%4==1) sum[i][u]+=Cos(u,b[u])*tmp;if(i%4==2) sum[i][u]+=-Sin(u,b[u])*tmp;if(i%4==3) sum[i][u]+=-Cos(u,b[u])*tmp;tmp*=a[u];}}if(ff[u]==2){double w=pow(E,b[u]);sum[0][u]+=w;fp(i,1,M) w*=a[u],sum[i][u]+=w;}if(ff[u]==3)sum[0][u]+=b[u],sum[1][u]+=a[u]; } il void pushr(re int u) {swap(t[u][0],t[u][1]);r[u]^=1; } il void pushdown(re int u) {if(r[u]){if(t[u][0]) pushr(t[u][0]);if(t[u][1]) pushr(t[u][1]);r[u]=0;} } il void rotate(re int x) {re int y=f[x],z=f[y],k=t[y][1]==x,v=t[x][!k];if(isrt(y)) t[z][t[z][1]==y]=x;t[x][!k]=y;t[y][k]=v;if(v) f[v]=y;f[y]=x;f[x]=z;pushup(y); } il void splay(re int u) {re int v=u,top=0;st[++top]=v;while(isrt(v)) st[++top]=v=f[v];while(top) pushdown(st[top--]);while(isrt(u)){v=f[u];top=f[v];if(isrt(v)) rotate((t[v][0]==u)^(t[top][0]==v)?v:u);rotate(u);}pushup(u); } il void access(re int u) {for(re int v=0;u;u=f[v=u]){splay(u),t[u][1]=v,pushup(u);} } il void makert(re int u) {access(u);splay(u);pushr(u); } il int findrt(re int u) {access(u);splay(u);while(t[u][0]) pushup(u),u=t[u][0];//return u; } il void split(re int u,re int v) {makert(u);access(v);splay(v); } il void link(re int u,re int v) {makert(u);if(findrt(v)!=u) f[u]=v; } il void cut(re int u,re int v) {split(u,v);//f[u]=t[v][0]=0;pushup(v); } int main() {freopen("math.in","r",stdin);freopen("math.out","w",stdout);ios::sync_with_stdio(false);jc[0]=1;fp(i,1,M) jc[i]=jc[i-1]*i;cin>>n>>m>>c;fp(i,1,n) cin>>ff[i]>>a[i]>>b[i];while(m--){re int u,v,w;cin>>op;if(op[0]=='a') cin>>u>>v,++u,++v,link(u,v);if(op[0]=='d') cin>>u>>v,++u,++v,cut(u,v);if(op[0]=='m') cin>>u,++u,makert(u),cin>>ff[u]>>a[u]>>b[u],ssin[u]=0,ccos[u]=0,pushup(u);if(op[0]=='t'){cin>>u>>v>>x;++u;++v;re double tmp=1;if(findrt(u)^findrt(v)) {puts("unreachable");continue;}split(u,v);ans=0;fp(i,0,M) ans+=sum[i][v]*tmp/jc[i],tmp*=x;printf("%.8e\n",ans);}}return 0; }轉載于:https://www.cnblogs.com/yanshannan/p/9439150.html
總結
以上是生活随笔為你收集整理的在美妙的数学王国中畅游的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JS排序算法之插入排序
- 下一篇: 净值小于1元的基金能买吗 注意这一点就