• noip模拟测试37


    考试总结:这次考试,难度不是很大,但是成绩却不太理想。看完题目,我多多少少都有一些思路,T1我看出了 \(ax+by=c\) 的不定方程求解,但我把板子给忘了,搞了快两个小时才搞出一组特解,但是因为特解会有负数,我当时就怀疑思路的正确性,也没仔细想,因为时间比较紧张,就把它弃了,然后是T2,我觉得和就是一道简单dp 加上线段树优化,码完了发现不对,这时候还剩差不多一个小时,我把自己hack之后也没有更正思路,就打了个测试点分治,然后搞T3,我觉得这是个最小生成树,边想边打,打完了发现自己思路不对,应该跑最短路,就打了个暴力的最短路,然后T4,觉得是个并查集,当时觉得根据真假在每个人之间连边,但是没有实现出来,总体来说,这次考试时间把握不够合理,发挥不是很好,同时我的一些知识点掌握不扎实,应该多加复习。

    T1 数列

    思路:对于一个数,我们要解方程 ax+by=m,并最小化 abs(x)+abs(y)。先用 exgcd
    求出一组解(x’,y’),那么解集是(x’+kb,y’-ka),
    证明: 若 ax+by=m,则 ax+by+kab-kab=m,移项,合并即可。
    显然 x 只会取最小的正值或最大的负值,那么我们就分别计算,取最小即可。
    补充芝士:扩展欧几里得,求 \(ax+by=gcd(a,b)\),
    \(gcd(a,b)=gcd(b,a\% b)\)
    \(ax_1+by_1=gcd(a,b)\)
    \(bx_2+(a\%b)y2=gcd(b,a\% b)\)
    我们可以将(a%b)写成\((a-\lfloor\frac{a}{b}\rfloor*b)\)
    将括号打开常数a,b合并,合并之后的结果为\(a*y_2+b*(x_2-\lfloor\frac{a}{b}\rfloor*y_2)\)
    我们将两式子联立,对比系数即可得到\(x_1=y_2\),\(x_1=y_2,y_1=x_2-\lfloor\frac{a}{b}\rfloor*y_2\)
    这样就可以求得一组x,y,那么一组满足条件(\(ax+by=c\))的特解 x 即为 \((x*(c/gcd)\%(b/gcd)+(b/gcd))\%(b/gcd)\)
    代码如下:

    AC_code
    #include<bits/stdc++.h>
    #define int long long
    #define re register int
    #define ii inline int
    #define iv inline void
    #define lc (rt<<1)
    #define rc (rt<<1|1)
    #define mid ((l+r)>>1)
    using namespace std;
    const int N=1e5+10;
    int n,a,b,c,x,y;
    int ans,gcd;
    ii read()
    {
    	int x=0;
    	bool f=1;
    	char ch=getchar();
    	while(ch<'0'||ch>'9')
    	{
    		if(ch=='-')
    			f=0;
    		ch=getchar();
    	}
    	while(ch>='0'&&ch<='9')
    	{
    		x=(x<<1)+(x<<3)+(ch^48);
    		ch=getchar();
    	}
    	return f?x:(-x);
    }
    iv oj(int i,int j)
    {
    	if(j==0)
    	{
    		x=1;
    		y=0;
    		gcd=i;
    		return;
    	}
    	oj(j,i%j);
    	int tmp=x;
    	x=y;
    	y=tmp-i/j*y;
    }
    signed main()
    {
    	n=read();
    	a=read();
    	b=read();
    	if(a<b)
    		swap(a,b);
    	oj(a,b);
    	a/=gcd;
    	b/=gcd;
    	int x1,y1,x2,y2,out;
    	bool br=0;
    	for(re i=1;i<=n;i++)
    	{
    		c=read();
    		if(c%gcd!=0||br)
    		{
    			br=1;
    			continue;
    		}
    		c/=gcd;
    		x1=(x*c+b)%b;
    		y1=(c-a*x1)/b;
    		out=abs(x1)+abs(y1);
    		if(x1<0)
    		{
    			x2=x1+((-x1)/b+1)*b;
    			y2=y1-((-x1)/b+1)*a;
    			out=min(out,abs(x2)+abs(y2));
    			
    			x2=x1+((-x1)/b)*b;
    			y2=y1-((-x1)/b)*a;
    			out=min(out,abs(x2)+abs(y2));
    		}
    		else
    		{
    			x2=x1-(x1/b)*b;
    			y2=y1+(x1/b)*a;
    			out=min(out,abs(x2)+abs(y2));
    			
    			x2=x1-(x1/b+1)*b;
    			y2=y1+(x1/b+1)*a;
    			out=min(out,abs(x2)+abs(y2));
    		}
    		if(y1<0)
    		{
    			y2=y1+((-y1)/a+1)*a;
    			x2=x1-((-y1)/a+1)*b;
    			out=min(out,abs(x2)+abs(y2));
    			
    			y2=y1+((-y1)/a)*a;
    			x2=x1-((-y1)/a)*b;
    			out=min(out,abs(x2)+abs(y2));
    		}
    		else
    		{
    			y2=y1-(y1/a)*a;
    			x2=x1+(y1/a)*b;
    			out=min(out,abs(x2)+abs(y2));
    			
    			y2=y1-(y1/a+1)*a;
    			x2=x1+(y1/a+1)*b;
    			out=min(out,abs(x2)+abs(y2));
    		}
    		ans+=out;
    	}
    	if(br)
    		printf("-1\n");
    	else
    		printf("%lld\n",ans);
    	return 0;
    }
    

    T2 数对

    这道题与之前的一道考试题比较类似,就是多了一个排序,如果不考虑排序问题,那么对于一个给定的序列S,我们就是要求出满足条件的最大权值和,设\(f_{i,j}\)表示前 i 个数中,最大a值为 j 的最大权值之和,那么考虑转移,因为限制条件同时有a,b, 所以我们根据当前 a与 b 的大小关系来分情况讨论,

    1. \(a_i<b_i\) 那么\(f_{i,j}=max(f_[i,j],f_{i-1,k}+val[i]) (1<=k<=a_i)\)
      \(f_{i,j}=max(f_{i,j},f_{i-1,j}+val_i) ,(a_i+1<=j<=b_i)\)
      2.\(a_i>=b_i\) 那么 \(f_{i,j}=max(f_{i,j},f_{i-1,k}+val_i),(1<=k<=b_i)\)
      那么现在我们考虑顺序问题,考虑两个数对(a i ,b i )和(a j ,b j ),如果 a i <b j 并且 b i >a j ,那么我们望 i 排在j 前面。对于相反的情况,我们希望 j 排在 i 前面。其余两种情况显然按 a+b 从小到大排列就可以满足所有的需求,
    60pts_朴素DP
    
    
    #include<bits/stdc++.h>
    #define int long long
    #define re register int
    #define ii inline int
    #define iv inline void
    #define lc (rt<<1)
    #define rc (rt<<1|1)
    #define mid ((l+r)>>1)
    using namespace std;
    const int N=1e5+10;
    int n,cnt,maxx,sum;
    int f[3100][6100],lsh[N<<1];
    struct node
    {
    	int x,y,w;
    	friend bool operator < (node a,node b)
    	{
    		if(a.x<b.y and b.x>a.y)
    			return 1;
    		else if(a.x>b.y and b.x<a.y)
    			return 0;
    		return (a.x+a.y)<(b.x+b.y); 
    	}
    }use[N];
    ii read()
    {
    	int x=0;
    	bool f=1;
    	char ch=getchar();
    	while(ch<'0'||ch>'9')
    	{
    		if(ch=='-')
    			f=0;
    		ch=getchar();
    	}
    	while(ch>='0'&&ch<='9')
    	{
    		x=(x<<1)+(x<<3)+(ch^48);
    		ch=getchar();
    	}
    	return f?x:(-x);
    }
    signed main()
    {
    	n=read();
    	int a,b,c;
    	for(re i=1;i<=n;i++)
    	{
    		a=read();
    		b=read();
    		c=read();
    		use[i].x=a;
    		use[i].y=b;
    		use[i].w=c;
    		lsh[++cnt]=a;
    		lsh[++cnt]=b;
    	}
    	sort(use+1,use+n+1);
    	sort(lsh+1,lsh+cnt+1);
    	cnt=unique(lsh+1,lsh+cnt+1)-lsh-1;
    	for(re i=1;i<=n;i++)
    	{
    		a=use[i].x;
    		b=use[i].y;
    		a=lower_bound(lsh+1,lsh+cnt+1,a)-lsh;
    		b=lower_bound(lsh+1,lsh+cnt+1,b)-lsh;
    		use[i].x=a;
    		use[i].y=b;
    		sum+=use[i].w;
    	}
    	f[1][use[1].x]=use[1].w;	
    	for(re i=2;i<=n;i++)
    	{
    		for(re j=1;j<=cnt;j++)
    			f[i][j]=f[i-1][j];
    		if(use[i].x<=use[i].y)
    		{
    			for(re j=1;j<=use[i].x;j++)
    				f[i][use[i].x]=max(f[i][use[i].x],f[i-1][j]+use[i].w);
    			for(re j=use[i].x+1;j<=use[i].y;j++)
    				f[i][j]=max(f[i][j],f[i-1][j]+use[i].w);
    		}
    		else
    		{
    			for(re j=1;j<=use[i].y;j++)
    				f[i][use[i].x]=max(f[i][use[i].x],f[i-1][j]+use[i].w);
    		}
    	}
    	for(re i=1;i<=n;i++)
    	{
    		for(re j=1;j<=cnt;j++)
    			maxx=max(maxx,f[i][j]);
    	}
    	cout<<maxx<<endl;
    	return 0;
    }
    
    
    AC_code,线段树优化
    #include<bits/stdc++.h>
    #define int long long
    #define re register int
    #define ii inline int
    #define iv inline void
    #define lc (rt<<1)
    #define rc (rt<<1|1)
    #define mid ((l+r)>>1)
    using namespace std;
    const int N=2e5+10;
    int n,cnt,maxx,sum,ans;
    int lsh[N<<1];
    struct node
    {
    	int x,y,w;
    	friend bool operator < (node a,node b)
    	{
    		if(a.x<b.y and b.x>a.y)
    			return 1;
    		else if(a.x>b.y and b.x<a.y)
    			return 0;
    		return (a.x+a.y)<(b.x+b.y); 
    	}
    }use[N];
    ii read()
    {
    	int x=0;
    	bool f=1;
    	char ch=getchar();
    	while(ch<'0'||ch>'9')
    	{
    		if(ch=='-')
    			f=0;
    		ch=getchar();
    	}
    	while(ch>='0'&&ch<='9')
    	{
    		x=(x<<1)+(x<<3)+(ch^48);
    		ch=getchar();
    	}
    	return f?x:(-x);
    }
    struct Segment_Tree
    {
    	int dp[N<<2],lazy[N<<2];
    	iv pp(int rt)
    	{
    		dp[rt]=max(dp[lc],dp[rc]);
    	}
    	iv pd(int rt)
    	{
    		if(lazy[rt])
    		{
    			dp[lc]+=lazy[rt];
    			dp[rc]+=lazy[rt];
    			lazy[lc]+=lazy[rt];
    			lazy[rc]+=lazy[rt];
    			lazy[rt]=0;
    		}
    	}
    	iv insert(int rt,int l,int r,int p,int z)
    	{
    		if(l==r)
    		{
    			dp[rt]=max(dp[rt],z);
    			return;
    		}
    		pd(rt);
    		if(mid>=p)
    			insert(lc,l,mid,p,z);
    		else
    			insert(rc,mid+1,r,p,z);
    		pp(rt);
    	}
    	iv updata(int rt,int l,int r,int L,int R,int z)
    	{
    		if(L>R||L>r||R<l)
    			return;
    		if(L<=l&&r<=R)
    		{
    			dp[rt]+=z;
    			lazy[rt]+=z;
    			return;
    		}
    		pd(rt);
    		if(mid>=L)
    			updata(lc,l,mid,L,R,z);
    		if(mid<R)
    			updata(rc,mid+1,r,L,R,z);
    		pp(rt);
    	}
    	ii query(int rt,int l,int r,int L,int R)
    	{
    		if(L>R)
    			return 0;
    		if(L<=l&&r<=R)
    			return dp[rt];
    		pd(rt);
    		if(mid>=R)
    			return query(lc,l,mid,L,R);
    		if(mid<L)
    			return query(rc,mid+1,r,L,R);
    		return max(query(lc,l,mid,L,R),query(rc,mid+1,r,L,R));
    	}
    }T;
    signed main()
    {
    	n=read();
    	int a,b,c;
    	for(re i=1;i<=n;i++)
    	{
    		a=read();
    		b=read();
    		c=read();
    		use[i].x=a;
    		use[i].y=b;
    		use[i].w=c;
    		lsh[++cnt]=a;
    		lsh[++cnt]=b;
    	}
    	sort(use+1,use+n+1);
    	sort(lsh+1,lsh+cnt+1);
    	cnt=unique(lsh+1,lsh+cnt+1)-lsh-1;
    	for(re i=1;i<=n;i++)
    	{
    		a=use[i].x;
    		b=use[i].y;
    		a=lower_bound(lsh+1,lsh+cnt+1,a)-lsh;
    		b=lower_bound(lsh+1,lsh+cnt+1,b)-lsh;
    		use[i].x=a;
    		use[i].y=b;
    	}
    	for(re i=1;i<=n;i++)
    	{
    		ans=0;
    		if(use[i].x<use[i].y)
    		{
    			ans=T.query(1,1,cnt,1,use[i].x);
    			T.insert(1,1,cnt,use[i].x,ans+use[i].w);
    			T.updata(1,1,cnt,use[i].x+1,use[i].y,use[i].w);
    		}
    		else
    		{
    			ans=T.query(1,1,cnt,1,use[i].y);
    			T.insert(1,1,cnt,use[i].x,ans+use[i].w);	
    		}
    	}
    	printf("%lld\n",T.query(1,1,cnt,1,cnt));
    	return 0;
    }
    

    T3 最小距离

    思路:这道题说白了就是一个多源最短路,在我们跑单源最短路(Dij)的时候我们刚开始将一个起点压进堆,这道题我们将所有特殊点压进堆里,然后更新出所有的dis数组,结束后我们枚举每条边,如果这条边两端的点不是由同一个源点更新的,那么就更新这两个源点之间的答案。
    代码如下:

    AC_code
    #include<bits/stdc++.h>
    #define int long long
    #define re register int
    #define ii inline int
    #define iv inline void
    #define lc (rt<<1)
    #define rc (rt<<1|1)
    #define mid ((l+r)>>1)
    #define next nettrr
    #define head hheees
    using namespace std;
    const int N=2e5+10;
    const int INF=1e17;
    struct node
    {
    	int s,w;
    	friend bool operator < (node a,node b)
    	{
    		return a.w>b.w;
    	}
    };
    struct CUN
    {
    	int st,ed,w;
    }use[N];
    priority_queue<node> Q;
    int n,m,p,tot;
    int to[N<<1],next[N<<1],head[N],val[N<<1];
    int csp[N],dis[N],be[N],my_min[N];
    bool sp[N],vis[N];
    ii read()
    {
    	int x=0;
    	bool f=1;
    	char ch=getchar();
    	while(ch<'0'||ch>'9')
    	{
    		if(ch=='-')
    			f=0;
    		ch=getchar();
    	}
    	while(ch>='0'&&ch<='9')
    	{
    		x=(x<<1)+(x<<3)+(ch^48);
    		ch=getchar();
    	}
    	return f?x:(-x);
    }
    iv add(int x,int y,int z)
    {
    	to[++tot]=y;
    	next[tot]=head[x];
    	head[x]=tot;
    	val[tot]=z;
    }
    ii gett(int x)
    {
    	if(x==be[x])
    		return x;
    	return be[x]=gett(be[x]);
    }
    iv dj()
    {
    	for(re i=1;i<=n;i++)
    	{
    		dis[i]=INF;
    		my_min[i]=INF;	
    	}
    	for(re i=1;i<=n;i++)
    		be[i]=i;
    	for(re i=1;i<=p;i++)
    	{
    		dis[csp[i]]=0;
    		Q.push((node){csp[i],0});	
    	}
    	while(!Q.empty())
    	{
    		int x=Q.top().s;
    		int y=Q.top().w;
    		Q.pop();
    		if(!vis[x])
    		{
    			vis[x]=1;
    			for(re i=head[x];i;i=next[i])
    			{
    				int p=to[i];
    				if(dis[p]>dis[x]+val[i])
    				{
    					dis[p]=dis[x]+val[i];
    					be[p]=gett(x);
    					Q.push((node){p,dis[p]});
    				}
    			}
    		}
    	}
    	for(re i=1;i<=m;i++)
    	{
    		int fx=gett(use[i].st),fy=gett(use[i].ed);
    		if(fx!=fy)
    		{
    			my_min[fx]=min(my_min[fx],dis[use[i].st]+dis[use[i].ed]+use[i].w);
    			my_min[fy]=min(my_min[fy],dis[use[i].st]+dis[use[i].ed]+use[i].w);
    		}
    	}
    	for(re i=1;i<=p;i++)
    		printf("%lld ",my_min[csp[i]]);
    }
    signed main()
    {
    	n=read();
    	m=read();
    	p=read();
    	for(re i=1;i<=p;i++)
    	{
    		csp[i]=read();
    		sp[csp[i]]=1;
    	}
    	int u,v,w;
    	for(re i=1;i<=m;i++)
    	{
    		u=read();
    		v=read();
    		w=read();
    		use[i].st=u;
    		use[i].ed=v;
    		use[i].w=w;
    		add(u,v,w);
    		add(v,u,w);
    	}
    	dj();
    	return 0;
    }
    
    

    T4 真相

    image

    65pts_code
    #include<bits/stdc++.h>
    #define int long long
    #define re register int
    #define ii inline int
    #define iv inline void
    #define lc (rt<<1)
    #define rc (rt<<1|1)
    #define mid ((l+r)>>1)
    using namespace std;
    const int N=1010;
    int n,t;
    char s[5];
    int js[N],cun[N],h[N];
    int pd[N];
    ii read()
    {
    	int x=0;
    	bool f=1;
    	char ch=getchar();
    	while(ch<'0'||ch>'9')
    	{
    		if(ch=='-')
    			f=0;
    		ch=getchar();
    	}
    	while(ch>='0'&&ch<='9')
    	{
    		x=(x<<1)+(x<<3)+(ch^48);
    		ch=getchar();
    	}
    	return f?x:(-x);
    }
    inline bool check()
    {
    	for(re i=2;i<=n;i++)
    	{
    		if(pd[i-1]==1)
    		{
    			if(cun[i-1]==-1)
    				pd[i]=1;
    			else
    				pd[i]=2;
    		}
    		else if(pd[i-1]==2)
    		{
    			if(cun[i-1]==-1)
    				pd[i]=2;
    			else
    				pd[i]=1;
    		}
    	}
    	if(pd[n]==1)
    	{
    		if(cun[n]==-1 and pd[1]==1)
    			return 1;
    		else if(cun[n]==-2 and pd[1]==2)
    			return 1;
    		return 0;
    	}
    	else if(pd[n]==2)
    	{
    		if(cun[n]==-1 and pd[1]==1)
    			return 0;
    		else if(cun[n]==-2 and pd[1]==2)
    			return 0;
    		return 1;
    	}
    }
    iv spe_1()
    {
    	int cnt=0;
    	memset(pd,0,sizeof(pd));
    	pd[1]=1;
    	if(check())
    	{
    		printf("consistent\n");
    		return;
    	}
    	memset(pd,0,sizeof(pd));
    	pd[1]=2;
    	if(check())
    		printf("consistent\n");
    	else
    		printf("inconsistent\n");
    	return ;
    }
    inline bool check_2(int x)
    {
    	int cnt=0;
    	for(re i=1;i<=h[0];i++)
    	{
    		int now=h[i];
    		while(1)
    		{
    			int la=now-1;
    			if(la==0)
    				la=n;
    			if(pd[la])
    				break;
    			if(pd[now]==1)
    			{
    				if(cun[la]==-1)
    					pd[la]=1;
    				else
    					pd[la]=2;
    			}
    			else
    			{
    				if(cun[la]==-1)
    					pd[la]=2;
    				else
    					pd[la]=1;
    			}
    			now=la;
    		}
    	}
    	for(re i=1;i<=n;i++)
    		if(pd[i]==1)
    			++cnt;
    	if(cnt==x)
    		return 1;
    	return 0;
    }
    iv spe_2()
    {
    	bool ke=0;
    	for(re i=0;i<=n;i++)
    	{
    		memset(pd,0,sizeof(pd));
    		for(re j=1;j<=h[0];j++)
    		{
    			if(cun[h[j]]!=i)
    				pd[h[j]]=2;
    			else
    				pd[h[j]]=1;
    		}
    		if(check_2(i))
    		{
    			ke=1;
    			break;
    		}
    	}
    	if(ke)
    		printf("consistent\n");
    	else
    		printf("inconsistent\n");
    	return ;
    }
    signed main()
    {
    	t=read();
    	while(t--)
    	{
    		n=read();
    		bool hav=0;
    		memset(cun,0,sizeof(cun));
    		memset(h,0,sizeof(h));
    		for(re i=1;i<=n;i++)
    		{
    			scanf("%s",s);
    			if(s[0]=='$')
    			{
    				hav=1;
    				cun[i]=read();
    				h[++h[0]]=i;
    			}
    			else if(s[0]=='+')
    			{
    				cun[i]=-1;	
    			}
    			else if(s[0]=='-')
    			{
    				cun[i]=-2;
    			}	
    		}
    		if(!hav)
    			spe_1();
    		else
    			spe_2();
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    十五分钟建立精美网站
    WebMatrix教程(一) (关注Microsoft 的最新武器:建立你的第一个WebMatrix网站)
    数据同步框架MS Sync Framework IDE快速开发支持Local Database Cache
    Interview SeniorSoftwareEngineers
    学JQuery最新免费教程[转]
    Visual Studio 2010 支持HTML5 和 CSS3
    Orchard:打包和共享模块
    CSLA.NET 框架开发实战
    如何真正提高ASP.NET网站的性能
    敏捷英语
  • 原文地址:https://www.cnblogs.com/WindZR/p/15135030.html
Copyright © 2020-2023  润新知