傳送門html
既然沒參加過就沒有什麼小裙子不小裙子的了……c++
順便全是機率指望真是勁啊……函數
\(k\)增加很是快,大力模擬一下就好了優化
int main(){ scanf("%lld",&x),sum=2; if(x==1)return puts("2"),0; fp(i,3,19260817){ sum+=(sum>>1); if(sum>x)return printf("%d\n",i),0; } return 0; }
賣出的指望價格確定是\(q={L+R\over 2}\)spa
而後分類討論,若是\(q\leq l\)收益是\(0\),不然收益爲\({(q-p)(p-l)\over r-l}\),上面是個二次函數,分類討論一下是否能取到最值便可code
//minamoto #include<bits/stdc++.h> #define R register #define inline __inline__ __attribute__((always_inline)) #define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i) #define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i) #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v) template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;} template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;} using namespace std; int l,r,li,ri; inline double sqr(R double x){return x*x;} int main(){ cin>>l>>r>>li>>ri; if((l<<1)>=li+ri)return puts("0.0000"),0; if((li+ri)*0.5-r<=r-l)return printf("%.4lf\n",0.25*sqr((li+ri)*0.5-l)/(r-l)),0; return printf("%.4lf\n",(li+ri)*0.5-r),0; }
咱們枚舉點集,計算這個點集合法的機率,發現這個機率只和集合大小有關,且\(i\)個點的集合合法機率爲\(\left({x\over y}\right)^{i(i-1)\over 2}\)htm
//minamoto #include<bits/stdc++.h> #define R register #define inline __inline__ __attribute__((always_inline)) #define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i) #define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i) #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v) template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;} template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;} using namespace std; const int N=1e5+5,P=998244353; inline int add(R int x,R int y){return x+y>=P?x+y-P:x+y;} inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;} inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;} int ksm(R int x,R int y){ R int res=1; for(;y;y>>=1,x=mul(x,x))(y&1)?res=mul(res,x):0; return res; } int fac[N],ifac[N],n,x,y,p,res,now,tmp; int main(){ scanf("%d%d%d",&n,&x,&y),p=mul(x,ksm(y,P-2)),tmp=now=res=1; fac[0]=ifac[0]=1;fp(i,1,n)fac[i]=mul(fac[i-1],i); ifac[n]=ksm(fac[n],P-2);fd(i,n-1,1)ifac[i]=mul(ifac[i+1],i+1); fp(i,1,n)res=add(res,1ll*fac[n]*ifac[i]%P*ifac[n-i]%P*now%P),tmp=mul(tmp,p),now=mul(now,tmp); printf("%d\n",res); return 0; }
首先\(S\)是一個點集,而一個點集的全部直徑一定有一個共同的中點(這個點可能在點上也可能在邊上),那麼咱們枚舉這個中點,若是一個點集的直徑爲\(p\),那麼全部到它的距離爲\({p\over 2}\)的點至少得選兩個,且這兩個屬於不一樣的子樹,而到它的距離小於\({p\over 2}\)的點能夠隨便選不選,直接\(dp\)一下就行了blog
//minamoto #include<bits/stdc++.h> #define R register #define inline __inline__ __attribute__((always_inline)) #define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i) #define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i) #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v) template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;} template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;} using namespace std; const int N=2005,P=998244353; inline void swap(R int &x,R int &y){R int t=x;x=y,y=t;} inline int add(R int x,R int y){return x+y>=P?x+y-P:x+y;} inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;} inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;} int ksm(R int x,R int y){ R int res=1; for(;y;y>>=1,x=mul(x,x))(y&1)?res=mul(res,x):0; return res; } struct eg{int v,nx;}e[N<<1];int head[N],tot=1; inline void Add(R int u,R int v){e[++tot]={v,head[u]},head[u]=tot;} int bin[N],sz[N],f[N],g[N],h[N],now[N],deg[N],n,mx; void clr(int u,int fa,int dep){ cmax(mx,dep); go(u)if(v!=fa)clr(v,u,dep+1); } void dfs(int u,int fa,int dep){ ++now[dep]; go(u)if(v!=fa)dfs(v,u,dep+1); } int main(){ // freopen("testdata.in","r",stdin); scanf("%d",&n),bin[0]=1; fp(i,1,n)bin[i]=mul(bin[i-1],2); for(R int i=1,u,v;i<n;++i)scanf("%d%d",&u,&v),Add(u,v),Add(v,u); fp(u,1,n){ fp(i,0,n)sz[i]=0,g[i]=1,h[i]=0; go(u){ mx=0,clr(v,u,1); fp(i,0,mx)now[i]=0; dfs(v,u,1); fp(i,1,mx)sz[i]+=now[i],g[i]=mul(g[i],bin[now[i]]),h[i]=add(h[i],bin[now[i]]-1); } ++sz[0]; fp(i,1,n)f[i<<1]=add(f[i<<1],mul(bin[sz[i-1]],dec(g[i],h[i]+1))),sz[i]+=sz[i-1]; } for(R int k=2,u,v;k<=tot;k+=2){ u=e[k].v,v=e[k^1].v; fp(i,0,n)sz[i]=0,g[i]=1,h[i]=0; for(int T=1;T<=2;swap(u,v),++T){ mx=0,clr(v,u,1); fp(i,0,mx)now[i]=0; dfs(v,u,1); fp(i,1,mx)sz[i]+=now[i],g[i]=mul(g[i],bin[now[i]]),h[i]=add(h[i],bin[now[i]]-1); } fp(i,1,n)f[(i<<1)-1]=add(f[(i<<1)-1],mul(bin[sz[i-1]],dec(g[i],h[i]+1))),sz[i]+=sz[i-1]; } fp(i,1,n-1)printf("%d\n",f[i]); return 0; }
勁啊……排序
醒了的機率很麻煩咱們考慮沒醒的機率,那麼本身不能醒,別人也不能讓它醒。設\(q_i\)表示\(i\)不醒的機率,\(p_i\)表示\(i\)不本身醒的機率,\(s_i\)表示\(i\)不吵醒\(to_i\)的機率,若是\(i\)不在環裏,那麼\(q_i=p_i\prod\limits_{to_v=i}\left(q_v+(1-q_v)s_v\right)\),直接拓撲排序一下便可遞歸
若是是在環裏事情就會變得比較辣手了。咱們發現環確定不會有連出去的邊,那麼就令拓撲排序以後的\(q\)做爲環裏的點的新的\(p_i\)
將環上的點依次編號爲\(1,2,3,...,m\),斷掉\((m,1)\)這條邊以後換變成了一條鏈,那麼對於這條鏈進行一次拓撲排序以後,\(q_m\)就是環上的\(m\)對應的\(q_m\)。破環成鏈,對於每個都計算就好了。設環的大小爲\(s\),這樣的複雜度是\(O(s^2)\)
考慮優化,由於最終的\(q_m\)必定是形如\(p_m\times (kx+b)\)的形式,其中\(x\)的值爲\(p_{m+1}\),那麼咱們只要能在計算不一樣的\(q\)的時候快速維護好\(k\)和\(b\)就能夠了,只要倒着轉移就好了,具體能夠看代碼
//minamoto #include<bits/stdc++.h> #define R register #define inline __inline__ __attribute__((always_inline)) #define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i) #define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i) #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v) template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;} template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;} using namespace std; char buf[1<<21],*p1=buf,*p2=buf; inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;} int read(){ R int res,f=1;R char ch; while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1); for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0'); return res*f; } char sr[1<<21],z[20];int K=-1,Z=0; inline void Ot(){fwrite(sr,1,K+1,stdout),K=-1;} void print(R int x){ if(K>1<<20)Ot();if(x<0)sr[++K]='-',x=-x; while(z[++Z]=x%10+48,x/=10); while(sr[++K]=z[Z],--Z);sr[++K]=' '; } const int N=1e5+5,P=998244353; inline int add(R int x,R int y){return x+y>=P?x+y-P:x+y;} inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;} inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;} int ksm(R int x,R int y){ R int res=1; for(;y;y>>=1,x=mul(x,x))(y&1)?res=mul(res,x):0; return res; } int to[N],deg[N],s[N],p[N],ans[N],vis[N],q[N],st[N],bb[N],kk[N],ip[N],is[N],n,top; void bfs(){ int h=1,t=0,u,v; fp(i,1,n)if(!deg[i])q[++t]=i; while(h<=t){ v=to[u=q[h++]],vis[u]=1,ans[u]=p[u]; p[v]=mul(p[v],add(p[u],mul(P+1-p[u],s[u]))); if(!--deg[v])q[++t]=v; } } int main(){ // freopen("testdata.in","r",stdin); // freopen("testdata.out","w",stdout); n=read(); for(R int i=1,x,y;i<=n;++i)x=read(),y=read(),p[i]=P+1-mul(x,ksm(y,P-2)); fp(i,1,n)to[i]=read(),++deg[to[i]]; for(R int i=1,x,y;i<=n;++i)x=read(),y=read(),s[i]=P+1-mul(x,ksm(y,P-2)); bfs(); fp(i,1,n)ip[i]=ksm(p[i],P-2),is[i]=ksm(P+1-s[i],P-2); fp(i,1,n)if(!vis[i]){ st[top=1]=i,vis[i]=1; for(R int u=to[i];u!=i;vis[u]=1,st[++top]=u,u=to[u]); fp(j,1,top)st[top+j]=st[j]; int k=1,b=0,kk,bb; fp(j,top+1,top+top-1){ k=mul(k,P+1-s[st[j]]),b=mul(b,P+1-s[st[j]]),b=add(b,s[st[j]]), k=mul(k,p[st[j+1]]),b=mul(b,p[st[j+1]]); } fd(j,top,1){ ans[st[j]]=add(mul(p[st[j+1]],k),b); k=mul(k,ip[st[j+top]]),b=mul(b,ip[st[j+top]]); b=dec(b,s[st[j+top-1]]),b=mul(b,is[st[j+top-1]]),k=mul(k,is[st[j+top-1]]); kk=k,bb=b; k=1ll*(P+1-s[st[j]])*p[st[j+1]]%P*kk%P,b=(1ll*s[st[j]]*p[st[j+1]]%P*kk%P+bb)%P; } } fp(i,1,n)print(P+1-ans[i]); return Ot(),0; }
咱們考慮分治,設
\[L(x)=\prod_{i=1}^{n/2}(p_ix+1-p_i)=\sum_{i=0}^{n/2}l_ix^i\]
\[R(x)=\prod_{i=n/2+1}^{n}(p_ix+1-p_i)=\sum_{i=0}^{n-n/2}r_ix^i\]
假設咱們須要計算\([1,n/2]\)中的答案,那麼最終答案確定是形如\(\sum_{j=0}^{n/2-1}\sum_{k=0}^{n-n/2}l'_jr_ka_{j+k}\),對於左邊的全部\(i\),\(r_k\)都是定值,那麼咱們能夠令\(a_j'=\sum\limits_{k=0}^{n-n/2}r_ka_{j+k}\)而後用\(a_j'\)遞歸左邊。\(a_j'\)是個卷積的形式,能夠快速計算
這樣的話複雜度就是\(O(n\log^2n)\)
//minamoto #include<bits/stdc++.h> #define R register #define inline __inline__ __attribute__((always_inline)) #define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i) #define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i) #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v) template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;} template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;} using namespace std; char buf[1<<21],*p1=buf,*p2=buf; inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;} int read(){ R int res,f=1;R char ch; while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1); for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0'); return res*f; } char sr[1<<21],z[20];int K=-1,Z=0; inline void Ot(){fwrite(sr,1,K+1,stdout),K=-1;} void print(R int x){ if(K>1<<20)Ot();if(x<0)sr[++K]='-',x=-x; while(z[++Z]=x%10+48,x/=10); while(sr[++K]=z[Z],--Z);sr[++K]=' '; } typedef vector<int> poly; const int N=(1<<18)+5,P=998244353; inline void swap(R int &x,R int &y){R int t=x;x=y,y=t;} inline int add(R int x,R int y){return x+y>=P?x+y-P:x+y;} inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;} inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;} int ksm(R int x,R int y){ R int res=1; for(;y;y>>=1,x=mul(x,x))(y&1)?res=mul(res,x):0; return res; } int r[21][N],rt[2][N],inv[21],lim,d; inline void init(R int len){lim=1,d=0;while(lim<len)lim<<=1,++d;} void Pre(){ fp(d,1,18){ fp(i,1,(1<<d)-1)r[d][i]=(r[d][i>>1]>>1)|((i&1)<<(d-1)); inv[d]=ksm(1<<d,P-2); } for(R int t=(P-1)>>1,i=1,x,y;i<262144;i<<=1,t>>=1){ x=ksm(3,t),y=ksm(332748118,t),rt[0][i]=rt[1][i]=1; fp(k,1,i-1) rt[1][i+k]=mul(rt[1][i+k-1],x), rt[0][i+k]=mul(rt[0][i+k-1],y); } } void NTT(int *A,int ty){ fp(i,0,lim-1)if(i<r[d][i])swap(A[i],A[r[d][i]]); R int t; for(R int mid=1;mid<lim;mid<<=1) for(R int j=0;j<lim;j+=(mid<<1)) fp(k,0,mid-1) A[j+k+mid]=dec(A[j+k],t=mul(rt[ty][mid+k],A[j+k+mid])), A[j+k]=add(A[j+k],t); if(!ty){ t=inv[d]; fp(i,0,lim-1)A[i]=mul(A[i],t); } } poly Mul(poly &a,poly &b){ int n=a.size(),m=b.size();poly c(n+m-1); if(n+m<233){ fp(i,0,n-1)fp(j,0,m-1)c[i+j]=add(c[i+j],mul(a[i],b[j])); return c; } static int f[N],g[N];init(n+m); fp(i,0,n-1)f[i]=a[i];fp(i,n,lim-1)f[i]=0; fp(i,0,m-1)g[i]=b[i];fp(i,m,lim-1)g[i]=0; NTT(f,1),NTT(g,1); fp(i,0,lim-1)f[i]=mul(f[i],g[i]); NTT(f,0); fp(i,0,n+m-2)c[i]=f[i]; return c; } poly exmul(poly &a,poly &b){ reverse(b.begin(),b.end()); int n=a.size(),m=b.size(); poly c=Mul(a,b),d(n-m+1); fp(i,0,n-m)d[i]=c[i+m-1]; return d; } poly pos[N<<2],ans[N<<2];int n; void solve(int p,int l,int r){ if(l==r){ int v=read();v=mul(v,ksm(read(),P-2)); pos[p].resize(2),pos[p][0]=P+1-v,pos[p][1]=v; return; } int mid=(l+r)>>1; solve(p<<1,l,mid),solve(p<<1|1,mid+1,r); pos[p]=Mul(pos[p<<1],pos[p<<1|1]); } void calc(int p,int l,int r){ if(l==r)return print(ans[p][0]),void(); int mid=(l+r)>>1; ans[p<<1]=exmul(ans[p],pos[p<<1|1]); ans[p<<1|1]=exmul(ans[p],pos[p<<1]); calc(p<<1,l,mid),calc(p<<1|1,mid+1,r); } int main(){ // freopen("testdata.in","r",stdin); n=read(),ans[1].resize(n),Pre(); fp(i,0,n-1)ans[1][i]=read(); solve(1,1,n),calc(1,1,n); return Ot(),0; }