• 11.2 正睿停课训练 Day15



    2018.11.2 正睿停课训练 Day15

    时间:3.5h
    期望得分:100+20+20
    实际得分:100+20+0

    比赛链接

    A 郁闷的小G(二分)

    题目链接

    //二分。
    #include <cstdio>
    #include <cctype>
    #include <algorithm>
    #define gc() getchar()
    typedef long long LL;
    
    inline LL read()
    {
    	LL now=0;register char c=gc();
    	for(;!isdigit(c);c=gc());
    	for(;isdigit(c);now=now*10+c-'0',c=gc());
    	return now;
    }
    inline bool Check(LL x,LL a,LL b,LL c,LL d,LL e)
    {
    	if(a<x) b-=x-a;
    	if(e<x) d-=x-e;
    	if(b<0||d<0) return 0;
    	LL tmp=b+d;
    	if(c<x) c+=tmp;
    	return c>=x;
    }
    
    int main()
    {
    	LL a=read(),b=read(),c=read(),d=read(),e=read();
    	LL l=0,r=2e18,mid,ans=0;
    	while(l<=r)
    		if(Check(mid=l+r>>1,a,b,c,d,e)) ans=mid,l=mid+1;
    		else r=mid-1;
    	printf("%lld
    ",ans);
    
    	return 0;
    }/*
    2 2 1 2 2
    100 100 100 0 0
    */
    

    B 小G的树(树形DP)

    题目链接

    求树的直径需要用到子树最长链与子树内的最大直径,都存下来就好了。
    (f[i][j][k])表示当前为点(i)(i)子树最长链长度为(j)(i)子树内最大直径为(k),的概率(直径不一定过点(i))。
    转移(O(n^4))就行了。
    概率(frac 12)可以最后乘,也就是两种可能的概率都算做(1)。同时存的数不会超过(2^{60}),所以可以用longlong。
    最后乘(frac{1}{2^{n-1}}),因为每条边的概率都乘了(2)

    //0ms	1080kb
    #include <cstdio>
    #include <cctype>
    #include <cstring>
    #include <algorithm>
    #define gc() getchar()
    typedef long long LL;
    const int N=62;
    
    int Enum,H[N],nxt[N<<1],to[N<<1],D[N];
    LL f[N][N<<1][N<<1];
    
    inline int read()
    {
    	int now=0;register char c=gc();
    	for(;!isdigit(c);c=gc());
    	for(;isdigit(c);now=now*10+c-'0',c=gc());
    	return now;
    }
    inline void AE(int u,int v)
    {
    	to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum;
    	to[++Enum]=u, nxt[Enum]=H[v], H[v]=Enum;
    }
    void Merge(int x,int v,int d1,int d2,int d3,int d4)
    {
    	static LL g[N<<1][N<<1];
    
    	LL (*fx)[N<<1]=f[x],(*fv)[N<<1]=f[v];
    	LL tmp,tmp2;
    	for(int a=0; a<=d1; ++a)
    		for(int b=a; b<=d2; ++b)
    			if((tmp=fx[a][b]))
    				for(int c=0; c<=d3; ++c)
    					for(int d=c; d<=d4; ++d)
    					{
    						if(!fv[c][d]) continue;
    						tmp2=tmp*fv[c][d];
    						g[std::max(a,c+1)][std::max(std::max(b,d),a+c+1)]+=tmp2,
    						g[std::max(a,c+2)][std::max(std::max(b,d),a+c+2)]+=tmp2;
    					}
    	int l1=std::max(d1,d3+2),l2=std::max(std::max(d2,d4),d1+d3+2);
    	for(int i=0; i<=l1; ++i)
    		for(int j=i; j<=l2; ++j) fx[i][j]=g[i][j], g[i][j]=0;
    }
    int DFS(int x,int fa)
    {
    	int mxd=0,dia=0; f[x][0][0]=1;
    	for(int i=H[x],v,d; i; i=nxt[i])
    		if((v=to[i])!=fa)
    		{
    			d=DFS(v,x), Merge(x,v,mxd,dia,d,D[v]);
    			dia=std::max(dia,std::max(D[v],mxd+d)), mxd=std::max(mxd,d);
    		}
    	return D[x]=dia, mxd+2;
    }
    
    int main()
    {
    	int n=read();
    	for(int i=1; i<n; ++i) AE(read(),read());
    	int d=DFS(1,1);
    	double ans=0;
    	for(int i=0; i<=d; ++i)
    		for(int j=i; j<=D[1]; ++j) ans+=1.0*f[1][i][j]*j;
    	printf("%.10lf
    ",ans/(1ll<<n-1));
    
    	return 0;
    }
    

    C 数的距离(思路)

    题目链接

    原题:HDU5812

    对于(dis(x,y)),把(x,y)质因数分解后(令(x=prod_{i=1}^k p_i^{a_i},y=prod_{i=1}^k p_i^{b_i})),则(dis(x,y)=sum_{i=1}^k |a_i-b_i|)
    实际上我们可以去掉(x,y)公共的部分,即令(f(x)=x的质因子个数),则(dis(x,y)=f(frac{x}{gcd(x,y)})+f(frac{y}{gcd(x,y)}))
    (f)可以线性筛预处理,即(f(frac{x}{gcd(x,y)}))可以直接得到。然后我们可以枚举(x)的约数(d)作为(gcd(x,y)),然后求(min{f(frac yd)}(y在集合中))

    不妨在插入(y)时,也枚举(y)的每个约数(d),然后更新(g(d)=min{g(d),f(frac yd)})(g(d))表示(f(frac yd)(y在集合中))的最小值。
    这样就可以(O(1))(min{f(frac yd)})了。

    但是还有删除操作,我们需要维护(g(d))的最小值。
    注意到(f(x))不会超过(20),且我们只关心(f(frac yd))的大小,所以可以用(cnt[d][t])表示(g(d))中满足(g(d)=t)(y)的个数,用一个二进制数(s[d])表示(g(d))中每个值的存在性。这样就可以(O(1))更新(g(d)),并在查询时直接用位运算找到最小的(g(d))
    (事实上用不到(f)数组,因为只需要在枚举约数的时候算下个数就行了)

    质因数种类是最多(7)个,但不代表就是(2,3,5,7,11,13,17)这些啊。。
    可以处理出每个数的一个质因数(p)(n)每次直接除(p[n]),就不用枚举质数了。

    另外看到这个就想到(k)维曼哈顿距离。。最大好像能做吧(就是复杂度有点大),求最小距离是不是不能做啊。。

    //646ms	87836kb
    #include <cstdio>
    #include <cctype>
    #include <vector>
    #include <algorithm>
    //#define gc() getchar()
    #define MAXIN 300000
    #define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
    const int N=1e6+3,INF=1e9;//P[7]={2,3,5,7,11,13,17};
    
    int Opt,Ans,A[7],P[7],p[N],cnt[N][20],s[N];//A[N][7],P[N][7] //卡我内存还行 
    char IN[MAXIN],*SS=IN,*TT=IN;
    
    inline int read()
    {
    	int now=0;register char c=gc();
    	for(;!isdigit(c);c=gc());
    	for(;isdigit(c);now=now*10+c-'0',c=gc());
    	return now;
    }
    void Init(const int n)
    {
    	static int P[N>>3];
    	static bool not_P[N];
    	for(int cnt=0,i=2; i<=n; ++i)
    	{
    		if(!not_P[i]) P[++cnt]=i, p[i]=i;
    		for(int j=1,v; j<=cnt&&(v=i*P[j])<=n; ++j)
    		{
    			not_P[v]=1, p[v]=P[j];
    			if(!(i%P[j])) break;
    		}
    	}
    }
    int Div(int x)
    {
    	int lim=-1,cnt;
    	while(x!=1)
    	{
    		P[++lim]=p[x], cnt=0;
    		while(!(x%P[lim])) ++cnt, x/=P[lim];
    		A[lim]=cnt;
    	}
    	return lim;
    }
    void DFS(int x,int sum,int d)
    {
    	if(x==-1)
    	{
    		switch(Opt)
    		{
    			case 0: if(++cnt[d][sum]==1) s[d]^=1<<sum; break;
    			case 1: if(--cnt[d][sum]==0) s[d]^=1<<sum; break;
    			case 2: if(s[d]) Ans=std::min(Ans,sum+__builtin_ctz(s[d])); break;
    		}
    		return;
    	}
    	for(int i=0; i<=A[x]; ++i)
    		DFS(x-1,sum+A[x]-i,d), d*=P[x];
    }
    
    int main()
    {
    	Init(1000000);
    	for(int x,tot=0,Q=read(); Q--; )
    	{
    		Opt=read()-1, x=read();
    		if(Opt==2)
    			if(tot) Ans=INF;
    			else {puts("-1"); continue;}
    		else if(cnt[x][0]^Opt) continue;
    
    		DFS(Div(x),0,1);
    		switch(Opt)
    		{
    			case 0: ++tot; break;
    			case 1: --tot; break;
    			case 2: printf("%d
    ",Ans==INF?-1:Ans); break;
    		}
    	}
    	return 0;
    }
    

    考试代码

    B

    #include <cstdio>
    #include <cctype>
    #include <cstring>
    #include <algorithm>
    #define gc() getchar()
    #define eps 1e-10
    typedef long long LL;
    const int N=64;
    
    int n,Enum,H[N],nxt[N<<1],to[N<<1],dgr[N];
    double f[N][N];
    
    inline int read()
    {
    	int now=0;register char c=gc();
    	for(;!isdigit(c);c=gc());
    	for(;isdigit(c);now=now*10+c-'0',c=gc());
    	return now;
    }
    inline void AE(int u,int v)
    {
    	++dgr[v], to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum;
    	++dgr[u], to[++Enum]=u, nxt[Enum]=H[v], H[v]=Enum;
    }
    int DFS(int x,int fa)
    {
    	if(dgr[x]==1&&x!=fa)
    		for(int i=0; i<=2*n; ++i) f[x][i]=1;
    	for(int i=H[x],v; i; i=nxt[i])
    		if((v=to[i])!=fa)
    		{
    			DFS(v,x);
    			for(int d=1; d<=2*n; ++d)
    			{
    				if(f[x][d]<eps) f[x][d]=1;
    				f[x][d]*=(f[v][d-1]*0.5+(d>1?f[v][d-2]*0.5:0));
    			}
    			
    		}
    	for(int i=0; i<=2*n; ++i) printf("f[%d][%d]=%.5lf
    ",x,i,f[x][i]);
    }
    
    int main()
    {
    //	freopen(".in","r",stdin);
    //	freopen(".out","w",stdout);
    
    	n=read();
    	for(int i=1; i<n; ++i) AE(read(),read());
    	double ans=0; int cnt=0;
    	for(int x=1; x<=n; ++x)
    	{
    		if(dgr[x]>1) continue;
    		++cnt;
    		for(int i=1; i<=n; ++i)
    		{
    			f[i][0]=0;
    			for(int j=1; j<=2*n; j+=4) f[i][j]=f[i][j+1]=f[i][j+2]=f[i][j+3]=0;
    			f[i][2*n-2]=f[i][2*n-1]=f[i][2*n]=0;
    		}
    		printf("
    now:%d
    ",x);
    		DFS(x,x);
    		for(int i=1; i<=2*n; ++i) ans+=(f[x][i]-f[x][i-1])*i, printf("ans+=%.5lf*%d=%.5lf
    ",f[x][i]-f[x][i-1],i,(f[x][i]-f[x][i-1])*i);
    	}
    	printf("%.10lf
    ",ans);
    	printf("%.10lf
    ",ans/cnt);
    
    	return 0;
    }/*
    5
    1 2 2 3 3 4 4 5
    4
    1 2 1 3 1 4
    7
    1 2 2 3 3 4 3 5 4 6 4 7
    */
    

    C

    #include <set>
    #include <queue>
    #include <cstdio>
    #include <cctype>
    #include <algorithm>
    #define gc() getchar()
    #define MAXIN 300000
    //#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
    typedef long long LL;
    const int N=1e6+5,P[7]={2,3,5,7,11,13,17};//7
    
    int A[N][7],L[N],R[N];
    bool vis[N],ins[N];
    std::multiset<int> st[130];
    char IN[MAXIN],*SS=IN,*TT=IN;
    
    inline int read()
    {
    	int now=0;register char c=gc();
    	for(;!isdigit(c);c=gc());
    	for(;isdigit(c);now=now*10+c-'0',c=gc());
    	return now;
    }
    inline void Div(int x)
    {
    	vis[x]=1;
    	for(int s=x,i=0; i<7; ++i)
    		if(!(x%P[i]))
    		{
    			int cnt=1; x/=P[i];
    			while(!(x%P[i])) ++cnt, x/=P[i];
    			A[s][i]=cnt;
    		}
    }
    
    int main()
    {
    //	freopen("ex_number1.in","r",stdin);
    //	freopen(".out","w",stdout);
    
    	int Q=read(); const int all=1<<7;
    //	for(int s=0; s<all; ++s) st[s].insert(-1),st[s].insert(100000000);
    	for(int x,tot=0,ed=0; Q--; )
    	{
    		switch(read())
    		{
    			case 1:
    			{
    				if(ins[x=read()]) break;
    				ins[x]=1, ++tot;
    				if(!vis[x]) Div(x);
    				R[ed]=x, L[x]=ed, ed=x;
    				break;
    			}
    			case 2:
    			{
    				if(!ins[x=read()]) break;
    				ins[x]=0, --tot;
    				L[R[x]]=L[x], R[L[x]]=R[x];
    				if(x==ed) ed=L[x];
    				break;
    			}
    			case 3: 
    			{
    				x=read();
    				if(!tot) {puts("-1"); break;}
    				if(!vis[x]) Div(x);
    				int *a=A[x],ans=1e9;
    				for(int i=R[0]; ; i=R[i])
    				{
    					int sum=0;
    					for(int j=0; j<7; ++j) sum+=std::abs(a[j]-A[i][j]);
    					ans=std::min(ans,sum);
    					if(i==ed) break;
    				}
    				printf("%d
    ",ans);
    				break;
    			}
    		}
    	}
    //	return 0;
    	for(int x,tot=0,ed=0; Q--; )
    	{
    		switch(read())
    		{
    			case 1:
    			{
    				if(ins[x=read()]) break;
    				ins[x]=1, ++tot;
    				if(!vis[x]) Div(x);
    				int *a=A[x];
    				printf("A[%d]: ",x); for(int i=0; i<7; ++i) printf("%d ",a[i]); puts("");
    				for(int s=0; s<all; ++s)
    				{
    					int sum=0;
    					for(int i=0; i<7; ++i)
    						sum+=(s>>i&1?a[i]:-a[i]);
    					st[s].insert(sum);
    					printf("Insert(%d,%d)
    ",s,sum);
    				}
    				break;
    			}
    			case 2:
    			{
    				if(!ins[x=read()]) break;
    				ins[x]=0, --tot;
    				int *a=A[x];
    				for(int s=0; s<all; ++s)
    				{
    					int sum=0;
    					for(int i=0; i<7; ++i)
    						sum+=(s>>i&1?a[i]:-a[i]);
    //					printf("Delete(%d)
    ",sum);
    					st[s].erase(st[s].find(sum));
    				}
    				break;
    			}
    			case 3: 
    			{
    				x=read();
    				if(!tot) {puts("-1"); break;}
    				if(!vis[x]) Div(x);
    				int *a=A[x],ans=0;
    				printf("A[%d]: ",x); for(int i=0; i<7; ++i) printf("%d ",a[i]); puts("");
    				for(int s=0; s<all; ++s)
    				{
    					int sum=0;
    					for(int i=0; i<7; ++i)
    						sum+=(s>>i&1?a[i]:-a[i]);
    //					std::multiset<int>::iterator it=st[s].upper_bound(sum);
    					ans=std::max(ans,std::max(*st[s].rbegin()-sum,sum-*st[s].begin()));
    					printf("s:%d sum:%d big:%d ",s,sum,*st[s].rbegin());
    					printf("small:%d
    ",*st[s].begin());
    //					ans=std::min(ans,*it-sum);
    //					printf("s:%d sum:%d big:%d ",s,sum,*it);
    //					ans=std::min(ans,sum-*(--it));
    //					printf("small:%d
    ",*it);
    				}
    				printf("%d
    ",ans);
    				break;
    			}
    		}
    	}
    	return 0;
    }/*
    12
    3
    1 20
    1 15
    3 30
    1 30
    3 30
    2 10
    3 27
    1 15
    2 15
    2 20
    2 30
    3 5
    */
    
  • 相关阅读:
    多线程案例龟兔赛跑
    不靠谱的事
    生命的价值并不止于自己的幸福
    我的高中搞笑班主任
    AgileChina参会笔记
    上美食
    程序中保留一个Dump
    骗子公司驾到
    我的《野蛮生长》书摘
    最近看的书的清单
  • 原文地址:https://www.cnblogs.com/SovietPower/p/9900210.html
Copyright © 2020-2023  润新知