ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【考试总结】2022-07-05

2022-07-06 17:32:34  阅读:158  来源: 互联网

标签:return ifac 05 int top 2022 mul inline 07


数叶子

点之间互相独立,对答案的贡献之和它的度数有关,设当前计算的点的度数为 \(d\)

此时问题本质上是在 \([1,m]\) 中放 \(d\) 块板,每种放法向答案贡献划分出来的 \(d+1\) 个区间两两相邻的长度的乘积

使用 \(x=\sum\limits_{i=1}^x[1]\) 的想法处理乘积,也就是让每相邻的一对计算长度乘积次,通过枚举 只包含一个点的区间的 可以达到这个效果

此时得到答案表达式为

\[\sum_{i=1}^n\binom{m-deg_i}{n-1-deg_i}(n-deg_i-1)!deg_i!\sum_{j=1}^m\binom{m-j}{deg_i-1}j(m-j+1) \]

用吸收恒等式处理 \(m-j+1\) 再直接枚举组合数上侧,再将 \(m-j+1\) 拆成 \(m+2-(j+1)\) 分别求和,一侧是直接上指标求和,另一个再用一遍吸收恒等式就能直接求和了

组合数处理很有技巧

Code Display
const int N=1e6+10;
int n,m,deg[N],fac[N],ifac[N];
int dfac1[N];
inline int binom(int n,int k){return mul(fac[n],mul(ifac[k],ifac[n-k]));}
inline int calc(int d){
	int res=mul(fac[d],fac[n-d-1]*d%mod);
	return mul(mul(dfac1[d+1],ifac[n-1-d]),res);
}
signed main(){
	freopen("leaf.in","r",stdin);
	freopen("leaf.out","w",stdout);
	n=1e6+1; fac[0]=1;
	for(int i=1;i<=n;++i) fac[i]=mul(fac[i-1],i);
	ifac[n]=ksm(fac[n],mod-2);
	for(int i=n;i>=1;--i) ifac[i-1]=mul(ifac[i],i);
	n=read(); m=read();
	for(int i=1;i<n;++i) deg[read()]++,deg[read()]++;
	dfac1[n]=1;
	for(int i=n-1;i>=1;--i) dfac1[i]=mul(dfac1[i+1],m-i+1);
	int d=1,v=1;
	for(int i=1;i<=n-1-d;++i) ckmul(v,m-d-i+1);
	int ans=0;
	for(int i=1;i<=n;++i){
		int coef=calc(deg[i]);
		auto Dfac=[&](int n,int m){
			int res=1;
			for(int i=1;i<=m;++i) ckmul(res,n-i+1);
			return res;	
		};
		int sum=(m+2)*Dfac(m+1,deg[i]+1)%mod*ifac[deg[i]+1]%mod-(deg[i]+1)*ifac[deg[i]+2]%mod*Dfac(m+2,deg[i]+2);
		sum=(sum%mod+mod)%mod;
		ans+=sum*coef%mod;
	}
	print(ans%mod);
	return 0;
}


多边形

二分答案 \(\rm R\) ,在平面直角坐标系上画出一个半径为 \(R\) 的圆,此时目标多边形的每条边都和该圆相切

求出来给定的 \(n\) 个点向这个圆的切线,称两个切点形成的劣弧为这个点在圆上对应的区间。那么多边形某条边和圆的切点在某个给定点的对应区间中等价于这个点在多边形外

问题变成了使用 \(m\) 个点覆盖圆上的 \(n\) 个已知区间,贪心得到 \(m\) 个点中的每一个都会在区间的端点上。

暴力做法就是枚举所有 \(n\) 个区间的 \(2n\) 个端点作为原点,展开成链之后在原点放一个,在没被覆盖的区间中右端点最小者在右端点放一个点。

这个过程可以先倍增优化,断环成链之后双指针扫出来每个区间的后继

不难发现根据这个做法,得到的多边形不一定闭合,所以这题是错题吗?水博的 dalao 们还请指教

Code Display
const int N=2e5+10;
const double pi=acos(-1);
int n,m,bz[20][N];
struct point{double x,y,angle,dist;}p[N];
struct interval{double l,r;}inter[N];
inline bool check(double R){
    for(int i=1;i<=n;++i){
        double tmp=acos(R/p[i].dist);
        inter[i].l=p[i].angle-tmp;
        inter[i].r=p[i].angle+tmp;
        if(inter[i].l<0) inter[i].l+=2*pi;
        if(inter[i].r<0) inter[i].r+=2*pi;
        if(inter[i].r<inter[i].l) inter[i].r+=2*pi;
        inter[i+n]={inter[i].l+2*pi,inter[i].r+2*pi};
    }
    sort(inter+1,inter+2*n+1,[&](interval a,interval b){return a.r<b.r;});
	int indic=1;
    for(int i=1;i<=n*2;++i){
        while(indic<=(n<<1)&&inter[indic].l<=inter[i].r) ++indic;
        if(indic<=2*n) bz[0][i]=indic;
        else bz[0][i]=0;
    }
    for(int i=1;i<=19;++i){
        for(int j=1;j<=(n<<1);++j) bz[i][j]=bz[i-1][bz[i-1][j]];
    }
    for(int i=1;i<=n;++i){
        int x=i;
        for(int j=19;j>=0;--j) if(m>>j&1) x=bz[j][x];
        if(!x||x>=n+i) return 1;
    }
    return 0;
}
int main(){
    freopen("polygon.in","r",stdin);
    freopen("polygon.out","w",stdout);
    n=read(); m=read();
    double l=0,r=1e10,ans=l;
    for(int i=1;i<=n;++i){
        p[i].x=read(),p[i].y=read();
        p[i].angle=atan2(p[i].y,p[i].x);
        p[i].dist=sqrt(p[i].x*p[i].x+p[i].y*p[i].y);
        ckmin(r,p[i].dist);
    }
    if(m>=n) printf("%.10lf\n",r),exit(0);
    while(r-l>1e-9){
        double mid=(l+r)/2;
        if(check(mid)) ans=mid,l=mid;
        else r=mid;
    }
    printf("%.10lf\n",ans);
    return 0;
}


树论

原题 Surprise me,本题将 \(d(x,y)^k\) 变成 \(\displaystyle\sum_{i=0}^k\binom ki (d_x-d_{\rm LCA})^i(d_y-d_{\rm LCA})^{k-i}\) 进行计算即可,那么需要记录虚树上边权

在从儿子转移到父亲的过程本质上是用 \((w+w')^k\) 代替 \(w^k\) 的过程,在树形 \(\rm DP\) 的过程中用二项式定理展开维护即可

时间复杂度 \(\Theta(n\log n(\log n+k^2))\)

Code Display
const int mod=998244353,N=1e5+10;
inline int add(int x,int y){return x+y>=mod?x+y-mod:x+y;}
inline int del(int x,int y){return x-y<0?x-y+mod:x-y;}
inline int mul(int x,int y){return x*y-x*y/mod*mod;}
inline void ckadd(int &x,int y){x=x+y>=mod?x+y-mod:x+y;}
inline void ckdel(int &x,int y){x=x-y<0?x-y+mod:x-y;}
inline void ckmul(int &x,int y){x=x*y-x*y/mod*mod;}
inline int ksm(int x,int y){int res=1; for(;y;y>>=1,ckmul(x,x)) if(y&1) ckmul(res,x); return res;}
int n,K,ans[20];
int inv[N],ifac[N],fac[N],pw[N][20];
int lg[N<<1],st[20][N<<1],inpos[N],scnt;
int tim,dfn[N],dep[N];
vector<int> G[N];
int phi[N],pri[N],mu[N],pcnt;
bool isc[N];
inline void dfs(int x,int fat){
    dep[x]=dep[fat]+1; 
	st[0][inpos[x]=++scnt]=x; 
	dfn[x]=++tim;
    for(auto t:G[x]) if(t^fat) dfs(t,x),st[0][++scnt]=x;
    return ;
}
inline int get_Lca(int x,int y){
    if(x==y) return x;
    x=inpos[x],y=inpos[y]; if(x>y) swap(x,y); int t=lg[y-x+1];
    int node1=st[t][x],node2=st[t][y-(1<<t)+1];
    if(dep[node1]>dep[node2]) return node2;
    return node1;
}
int stk[N],top;
vector<int> virt[N];
int nowd,dp[N][20],coef[N];
inline void insert(int x){
    if(top<=1){stk[++top]=x; return ;}
    int tl=get_Lca(x,stk[top]);
    while(top>1&&dfn[stk[top-1]]>=dfn[tl]) virt[stk[top-1]].emplace_back(stk[top]),--top;
    if(stk[top]^tl) virt[tl].emplace_back(stk[top]),stk[top]=tl;
    return stk[++top]=x,void();
}
inline void DP(int x){
    if(x%nowd==0) dp[x][0]=phi[x];
    for(auto t:virt[x]){
        DP(t);
        for(int i=K;i>=0;--i) if(dp[t][i]){
            for(int j=1;j+i<=K;++j){
                int coef=mul(ifac[j],pw[dep[t]-dep[x]][j]);
                (dp[t][i+j]+=coef*dp[t][i])%=mod;
            }
        }
        for(int i=0;i<=K;++i) if(dp[x][i]) for(int j=0;i+j<=K;++j){
            ans[i+j]+=coef[nowd]*dp[x][i]%mod*dp[t][j]%mod;
        }
        for(int i=0;i<=K;++i) ckadd(dp[x][i],dp[t][i]);
    } 
    return ;
}
inline void clear(int x){
    for(auto t:virt[x]) clear(t);
    memset(dp[x],0,sizeof(dp[x]));
    virt[x].clear(); 
    return ;
}
int node[N],cnt;
signed main(){
    freopen("tree.in","r",stdin);
    freopen("tree.out","w",stdout);
    n=1e5; K=10;
    inv[0]=fac[0]=pw[0][0]=1;
    for(int i=1;i<=n;++i){
        fac[i]=mul(fac[i-1],i);
        pw[i][0]=1;
        for(int j=1;j<=K;++j) pw[i][j]=mul(pw[i][j-1],i); 
    }
    ifac[n]=ksm(fac[n],mod-2);
    for(int i=n;i>=1;--i){
        ifac[i-1]=mul(ifac[i],i);
        inv[i]=mul(ifac[i],fac[i-1]);
    }
    for(int i=2;i<=n;++i){
        if(!isc[i]){
            pri[++pcnt]=i;
            phi[i]=i-1;
            mu[i]=-1;
        }
        for(int j=1;j<=pcnt&&i*pri[j]<=n;++j){
            isc[i*pri[j]]=1;
            if(i%pri[j]==0){
                phi[i*pri[j]]=phi[i]*pri[j]; 
                mu[i*pri[j]]=0; 
                break;
            }
            phi[i*pri[j]]=phi[i]*(pri[j]-1);
            mu[i*pri[j]]=-mu[i];
        }
    }
    n=read(); K=read();
    phi[1]=mu[1]=1;
    for(int i=1;i<n;++i){
        int u=read(),v=read();
        G[u].emplace_back(v); 
		G[v].emplace_back(u);
    }
    dfs(1,0);
    for(int j=1;j<=19;++j){
        for(int i=1;i+(1<<j)-1<=scnt;++i){
            if(dep[st[j-1][i]]<dep[st[j-1][i+(1<<(j-1))]]) st[j][i]=st[j-1][i];
            else st[j][i]=st[j-1][i+(1<<(j-1))];
        }
    }
    for(int i=2;i<=scnt;++i) lg[i]=lg[i>>1]+1;
    for(int i=1;i<=n;++i){
        for(int j=i;j<=n;j+=i){
            coef[j]=(coef[j]+inv[phi[i]]*i*mu[j/i]%mod+mod)%mod;
        }
    }
    for(int d=1;d<=n;++d){
        cnt=0;
        for(int j=d;j<=n;j+=d) node[++cnt]=j;
        sort(node+1,node+cnt+1,[&](int x,int y){return dfn[x]<dfn[y];});
        stk[++top]=1;
        for(int i=1;i<=cnt;++i) if(node[i]!=1) insert(node[i]);
        for(int i=1;i<top;++i) virt[stk[i]].emplace_back(stk[i+1]);
        nowd=d;
        DP(1);
        clear(1);
        top=0;
    }
    for(int i=0;i<=K;++i) ans[i]=ans[i]%mod*2*fac[i]%mod;
    for(int i=1;i<=n;++i) (ans[0]+=i*phi[i])%=mod;
    for(int i=0;i<=K;++i) print(ans[i]);
    return 0;
}


标签:return,ifac,05,int,top,2022,mul,inline,07
来源: https://www.cnblogs.com/yspm/p/TestReview20220705.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有