2020.2.7比赛
电路图一系列。
这套题真的respect。
第一眼看到题的时候真的头都大了。再加上明明在家放假。真是一点想做它的欲望也没有。
结果只把第一题弄出来了QAQ。还好大家都只ac了这一道hhh。
电路图A
这道题看着很复杂很难搞的样子。实际上确实有点难搞orz。
我盯了它好久好久才终于看出来这是道组合数学,一开始真的没什么思路。
然后就比较好办了,就推推推,把公式规律推出来,就ok了。
数据范围有点大,多模一模,开long long也就问题不大了。
ans1=C(n,n/2-2).
ans2=C(n/2+1,4)*2+C(n/2+1,3).
#include<bits/stdc++.h> #define ll long long using namespace std; const ll mod=1000000007; ll f[100000005]; ll st(ll a,ll b) { ll ans=1; a%=mod; while(b) { if(b&1)ans=ans*a%mod; b>>=1; a=a*a%mod; } return ans; } ll C(ll n,ll m) { return f[n]*st(f[m],mod-2)%mod*st(f[n-m],mod-2)%mod; } int main() { ll n; scanf("%d",&n); f[0]=1; for(ll i=1;i<=n;i++) f[i]=f[i-1]*i%mod; ll m=n/2+2; cout<<C(n,m)<<endl; cout<<(2*C(m-1,4)%mod+C(m-1,3))%mod; }
电路图B
考试的时候花了好长的时间才回忆起初中物理讲的串并联知识。
串联:R=R1+R2.
并联:R=R1*R2/(R1+R2).
然后很明显要用线段树来做。
然后我半个小时把这个题打了出来。然后样例都过不了orz。然后我就开始调试、找错,然后又打了一个多小时。然后我看到大佬们都交了两三道题了,我就有点慌。然后我真的不知道为什么哪里错了我就是连样例都过不了orz。然后不知不觉比赛就结束了QAQ。
据说直接线段树有70分,我有点难受。
比赛完了上网搜题解的时候,看到要用神奇的线段树(?)才能A掉这道题。
对于一个函数(a,b,c,d)表示一个R=(a*x+b)/(c*x+d)。
串联就可表示成(1,R,0,1),并联就可表示成(R,0,1,R)。
合并时,原电阻(a,b,c,d)与另一电阻(a',b',c',d')合并可得新电阻表示为(a'*a+b'*c,a'*b+b'*d,c'*a+d'*c,c'*b+d'*d)。
题目虽然精度不限,但大佬说保存10以下精度过不了?我没试过,就直接保存10精度了。
#include<bits/stdc++.h> using namespace std; #define ld long double int n,g[250010],m,op,ql,qr,md; ld ans; struct ahj { ld a,b,c,d,mx,mn; }s[1000010]; void merge(ahj &x,ahj y) { x.mn=(x.mn*y.a+y.b)/(x.mn*y.c+y.d); x.mx=(x.mx*y.a+y.b)/(x.mx*y.c+y.d); ld a=y.a*x.a+y.b*x.c; ld b=y.a*x.b+y.b*x.d; ld c=y.c*x.a+y.d*x.c; ld d=y.c*x.b+y.d*x.d; x=(ahj){1,b/a,c/a,d/a,x.mx,x.mn}; } void clear(ahj &x) { x.a=x.d=1; x.b=x.c=0; } void pd(int x) { merge(s[x*2],s[x]); merge(s[x*2+1],s[x]); clear(s[x]); } void build(int x,int l,int r) { clear(s[x]); if(l==r) { s[x].mn=s[x].mx=g[l]; return; } int mid=(l+r)/2; build(x*2,l,mid);build(x*2+1,mid+1,r); s[x].mn=min(s[x*2].mn,s[x*2+1].mn); s[x].mx=max(s[x*2].mx,s[x*2+1].mx); } ld calc(ld x,ld y) { return (x*y)/(x+y); } void q(int x,int l,int r) { if(l!=r)pd(x); if(qr<l||r<ql) return; if(ql<=l&&r<=qr) { if(op==1)ans=max(ans,s[x].mx); if(op==2)ans=min(ans,s[x].mn); if(op==3) s[x]=(ahj){1,md,0,1,s[x].mx+md,s[x].mn+md}; if(op==4) s[x]=(ahj){md,0,1,md,calc(s[x].mx,md),calc(s[x].mn,md)}; return; } int mid=(l+r)/2; q(x*2,l,mid);q(x*2+1,mid+1,r); if(op>=3) { s[x].mn=min(s[x*2].mn,s[x*2+1].mn); s[x].mx=max(s[x*2].mx,s[x*2+1].mx); } } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&g[i]); build(1,1,n); scanf("%d",&m); while(m--) { scanf("%d%d%d",&op,&ql,&qr); if(op==1||op==2) { if(op==1) ans=-1e15; else ans=1e15; q(1,1,n); printf("%.10Lf\n",ans); } else { scanf("%d",&md); q(1,1,n); } } }