【2012 Multi-University Training Contest 7】部分题

48 篇文章 0 订阅
23 篇文章 0 订阅

适应acm赛制看来不是我原先想的那么简单...

4360

双关键字单源最短路

这道题我交了10+次,原因是初始化没取最小值...看来确实是太久没在考试状态下写题了,心中竟然还在紧张

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
const long long oo=1314520LL*13520LL+1;
using namespace std;
int n,m,ss,t;
int next[2000000],sora[2000000],pow[2000000],tail[2000000];
long long cost[2000000],d[2000][4];
int dd[2000][4],st[2000000][2];
bool v[2000][4];
char ch[2000];
void origin()
{
	ss=n;
	for (int i=0;i<=n;i++) tail[i]=i,next[i]=0;
	ch['L']=0,ch['O']=1,ch['V']=2,ch['E']=3;
}
void link(int x,int y,int z,int c)
{
	++ss,next[tail[x]]=ss,tail[x]=ss,sora[ss]=y,cost[ss]=z,pow[ss]=c,next[ss]=0;
	++ss,next[tail[y]]=ss,tail[y]=ss,sora[ss]=x,cost[ss]=z,pow[ss]=c,next[ss]=0;
}
void spfa(int s)
{
	int h,r=h=0,ne,na,tmp,ns;
	memset(v,0,sizeof(v));
	memset(d,127,sizeof(d)),memset(dd,129,sizeof(dd));
	for (int i=s;next[i];) {
		i=next[i],ne=sora[i];
		if (pow[i]==0) {
			d[ne][0]=min(d[ne][0],cost[i]);
			dd[ne][0]=1;
			st[++r][0]=ne,st[r][1]=0;
			v[ne][0]=1;
		}
	}
	for (;h<r;) {
		ne=st[++h][0],ns=st[h][1];
		for (int i=ne;next[i];) {
			i=next[i],na=sora[i],tmp=pow[i];
			if ((ns+1)%4==pow[i]) 
				if (d[ne][ns]+cost[i]<d[na][tmp] || ((d[ne][ns]+cost[i]==d[na][tmp]) && (dd[ne][ns]+1>dd[na][tmp]))) {
					d[na][tmp]=d[ne][ns]+cost[i],dd[na][tmp]=dd[ne][ns]+1;
					if (!v[na][tmp]) {
						v[na][tmp]=1;
						st[++r][0]=na,st[r][1]=tmp;
					}
				}
		}
		v[ne][ns]=0;
	}
}
void init(int cas)
{
	int x,y,z;
	//char ch1,ch2;
	scanf("%d%d\n",&n,&m);
	origin();
	char ch2[100]={};
	for (int i=1;i<=m;i++) {
		scanf("%d%d%d%s\n",&x,&y,&z,ch2);
		link(x,y,z,ch[ch2[0]]);
	}
	/*if (1==n) {
		printf("Case %d: Cute Sangsang, Binbin will come with a donkey after travelling %I64d meters and finding %d LOVE strings at last.\n",cas,0,0);
		return ;
	}*/
	spfa(1);
	if (d[n][3]>=d[0][0]) printf("Case %d: Binbin you disappoint Sangsang again, damn it!\n",cas);
	else printf("Case %d: Cute Sangsang, Binbin will come with a donkey after travelling %I64d meters and finding %d LOVE strings at last.\n",cas,d[n][3],dd[n][3]/4);
}
int main()
{
	freopen("input.txt","r",stdin);
	freopen("output.txt","w",stdout);
	cin>>t;
	for (int i=1;i<=t;i++)  init(i);
	return 0;
}

4362

dp+单调指针

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
int ans,f[100][2000],n,m,a[100][2000],b[100][2000],x,t,u[100][2000],e,mi;
bool cmp(int i,int j)
{
	return a[e][i]<a[e][j];
}
void init()
{
	scanf("%d%d%d\n",&m,&n,&x);
	for (int i=1;i<=m;i++)
		for (int j=1;j<=n;j++) scanf("%d",&a[i][j]),u[i][j]=j;
	for (int i=1;i<=m;i++)
		for (int j=1;j<=n;j++) scanf("%d",&b[i][j]);
	memset(f,127,sizeof(f));
	e=1;
	sort(u[1]+1,u[1]+n+1,cmp); 
	for (int i=1;i<=n;i++) f[1][i]=abs(x-a[1][u[1][i]])+b[1][u[1][i]];
	for (int i=2;i<=m;i++) {
		e=i;
		sort(u[i]+1,u[i]+n+1,cmp);
		mi=f[0][0];
		for (int j=1,k=1;j<=n;j++) {
			for (;(k<=n) && (a[i-1][u[i-1][k]]<=a[i][u[i][j]]);k++) 
				mi=min(mi,f[i-1][k]-a[i-1][u[i-1][k]]);
			if (mi!=f[0][0]) f[i][j]=min(f[i][j],mi+b[i][u[i][j]]+a[i][u[i][j]]);
		}
		mi=f[0][0];
		for (int j=n,k=n;j>=1;j--) {
			for (;(k>=1) && (a[i-1][u[i-1][k]]>=a[i][u[i][j]]);k--) 
				mi=min(mi,f[i-1][k]+a[i-1][u[i-1][k]]);
			if (mi!=f[0][0]) f[i][j]=min(f[i][j],mi+b[i][u[i][j]]-a[i][u[i][j]]);
		}
	}
	ans=f[0][0];
	for (int i=1;i<=n;i++) ans=min(ans,f[m][i]);
	printf("%d\n",ans);
} 
int main()
{
	freopen("input.txt","r",stdin);
	freopen("output.txt","w",stdout);
	cin>>t;
	for (;t;t--) init();
	return 0;
}

4363

dp->打表

dp各种特判,不过考虑和写的时候还蛮谨慎的,一遍过

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
const long long mo=1000000007LL;
using namespace std;
int n,m,time,o[5];
long long f[41][41][5][5][5][5][2];
int doit(int i,int j,int k,int p)
{
	int v[5]={};
	v[i]=v[j]=v[k]=v[p]=1;
	int sum=0;
	for (int i=1;i<=4;i++)
		sum+=(v[i]==0);
	return sum;
}
int main()
{
	freopen("input.txt","r",stdin);
	freopen("output.txt","w",stdout);
	n=m=40;
	time=0;
	memset(f,0,sizeof(f));
	for (int i=0;i<=4;i++)
		for (int j=0;j<=4;j++) 
			for (int k=0;k<=4;k++)
				for (int p=0;p<=4;p++) {
					++time;
					o[i]=o[j]=o[k]=o[p]=time;
					for (int y=1;y<=4;y++)
						if (o[y]!=time) {
							f[1][1][i][j][k][p][0]++;
							f[1][1][i][j][k][p][1]++;
						}
				}
	for (int c=1;c<=n;c++)
		for (int h=1;h<=m;h++) {
			if (c==1 && h==1) continue;
			for (int e=0;e<=1;e++)
			for (int i=0;i<=4;i++) 
				for (int j=0;j<=4;j++)
					for (int k=0;k<=4;k++)
						for (int p=0;p<=4;p++) {
							++time;
							o[i]=o[j]=o[k]=o[p]=time;
							for (int y=1;y<=4;y++)
								if (o[y]!=time) {
									f[c][h][i][j][k][p][e]++;
								}
							if (!e) {
								++time;
								o[i]=o[j]=o[k]=time;
								for (int y=1;y<=4;y++)
									if (o[y]!=time) {
										f[c][h][i][j][k][p][e]+=(c-1)*doit(i,y,k,p);
									}
								for (int v=1;v<c;v++) {
									for (int y=1;y<=4;y++)
										if (o[y]!=time) { 
											(f[c][h][i][j][k][p][e]+=f[c-v][h][i][y][k][p][e^1]-doit(i,y,k,p)+mo)%=mo;
										}	
								}
								++time;
								o[i]=o[p]=o[k]=time;
								for (int v=1;v<c;v++) {
									for (int y=1;y<=4;y++)
										if (o[y]!=time) { 
											(f[c][h][i][j][k][p][e]+=f[v][h][i][j][k][y][e^1]-doit(i,j,k,y)+mo)%=mo;
										}
								}
							}
							if (e) {
								++time;
								o[i]=o[j]=o[p]=time;
								for (int y=1;y<=4;y++)
									if (o[y]!=time) {
										f[c][h][i][j][k][p][e]+=(h-1)*doit(y,j,k,p);
									}
								for (int v=1;v<h;v++) {
									for (int y=1;y<=4;y++)
								 	if (o[y]!=time) {
									 	(f[c][h][i][j][k][p][e]+=f[c][h-v][y][j][k][p][e^1]-doit(y,j,k,p)+mo)%=mo;
									}
								}
								++time;
								o[j]=o[k]=o[p]=time; 
								for (int v=1;v<h;v++) {
									for (int y=1;y<=4;y++)
								 	if (o[y]!=time) {
									 	(f[c][h][i][j][k][p][e]+=f[c][v][i][j][y][p][e^1]-doit(i,j,y,p)+mo)%=mo;
									}
								}
							}
						}
		}
		for (int i=1;i<=n;i++) {
			printf("{0,");
			for (int j=1;j<=m;j++) {
			 	printf("%lldLL",(f[i][j][0][0][0][0][0]+mo)%mo);
			 	if (j!=m) printf(",");
			}
			printf("},\n");
		}
	return 0;
}

4364

模拟

比赛时题都没读...不过理解题意确实有点麻烦,最坑的是,输出时只保留两个字节,一开始不知道wa在哪,最后阴差阳错改了输出给过了...

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
const int lim=15*16+15;
using namespace std;
struct mt{int m[5][5];}o,a,c;
int t;
char ch[20000];
int doit(int x,int y)
{
	if (1==x) return y;
	else if (2==x) {
		y<<=1;
		if (y>lim) return y^(16+11);
		return y;
	}
	else {
		int z=y;
		y<<=1;
		if (y>lim) y=y^(16+11);
		return y^z;
	}
}
void mul(mt &ans,mt a,mt b)
{
	memset(ans.m,0,sizeof(ans.m));
	for (int i=1;i<=4;i++)
		for (int j=1;j<=4;j++)
			for (int k=1;k<=4;k++) {
				ans.m[i][j]^=doit(a.m[i][k],b.m[k][j]);
			}
}
void init()
{
	memset(a.m,0,sizeof(a.m));
	for (int i=1;i<=4;i++) {
		for (int j=1;j<=4;j++) {
			scanf("%s",ch+1);
			if (ch[1]>='A' && ch[1]<='Z') a.m[i][j]=(ch[1]-'A'+10)*16;
			else a.m[i][j]=(ch[1]-'0')*16;
			if (ch[2]>='A' && ch[2]<='Z') a.m[i][j]+=ch[2]-'A'+10;
			else a.m[i][j]+=ch[2]-'0';
		}
		scanf("\n");
	}
	mul(c,o,a);
	for (int i=1;i<=4;i++) {
		for (int j=1;j<=4;j++) {
			int ans[5]={},s=0;
			for (;c.m[i][j];c.m[i][j]/=16) ans[++s]=c.m[i][j]%16;
			for (s=2;s;s--)
				if (ans[s]>=10) printf("%c",ans[s]-10+'A');
				else printf("%d",ans[s]);
			if (j!=4) printf(" ");
//			printf(" ");
		}
		printf("\n");
	}
	if (t>1) printf("\n");
	//printf("\n");
}
int main()
{
	freopen("input.txt","r",stdin);
	freopen("ansput.txt","w",stdout);
	o.m[1][1]=2,o.m[1][2]=3,o.m[1][3]=1,o.m[1][4]=1;
	o.m[2][1]=1,o.m[2][2]=2,o.m[2][3]=3,o.m[2][4]=1;
	o.m[3][1]=1,o.m[3][2]=1,o.m[3][3]=2,o.m[3][4]=3;
	o.m[4][1]=3,o.m[4][2]=1,o.m[4][3]=1,o.m[4][4]=2;
	scanf("%d\n",&t);
	for (;t;t--) init();
	return 0;
}
4365

归一到一个三角形的等价类中,快速幂

比赛时没时间调了,结果只归一到左上角矩阵中

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
const long long mo=100000007LL;
using namespace std;
long long n,m,tot,ans,k;
int x[2000000],y[2000000],u[2000000];
long long fgm(long long b,long long e,long long mo)
{
	long long ans=1;
	for (;e;b=(b*b)%mo,e>>=1)
		if (e&1) ans=(ans*b)%mo;
	return ans;
}
bool cmp(int i,int j)
{
	if (x[i]!=x[j]) return x[i]<x[j];
	return y[i]<y[j];
}
void init()
{
	tot=m;
	for (int i=1;i<=m;i++) {
		scanf("%d%d\n",&x[i],&y[i]);x[i]++,y[i]++;
		++tot;
		x[tot]=y[i],y[tot]=n-x[i]+1;
		++tot;
		x[tot]=n-x[i]+1,y[tot]=n-y[i]+1;
		++tot;
		x[tot]=n-y[i]+1,y[tot]=x[i];
	}
	m=tot;
	for (int i=1;i<=m;i++) {
		++tot;
		x[tot]=x[i],y[tot]=n-y[i]+1;
		++tot;
		x[tot]=n-x[i]+1,y[tot]=y[i];
	}
	for (int i=1;i<=tot;i++) u[i]=i;
	sort(u+1,u+tot+1,cmp);
	x[0]=y[0]=u[0]=0;
	if (n&1) {
		ans=((n/2+1)*(n/2+1)-(n/2+1))/2+(n/2+1);
	}
	else {
		ans=((n/2)*(n/2)-n/2)/2+n/2;
	}
	for (int i=1;i<=tot;i++)
		if (x[u[i]]!=x[u[i-1]] || y[u[i]]!=y[u[i-1]]) {
			if (n&1) {
				if (x[u[i]]<=n/2+1 && y[u[i]]>=x[u[i]] && y[u[i]]<=n/2+1) ans--;
			}
			else {
				if (x[u[i]]<=n/2 && y[u[i]]>=x[u[i]] && y[u[i]]<=n/2) ans--;
			}
		}
	cout<<fgm(k,ans,mo)<<endl;
}
int main()
{
	freopen("input.txt","r",stdin);
	freopen("output.txt","w",stdout);
	for (;cin>>n>>m>>k;) init();
	return 0;
}

4366

先维护数值大小,再维护dfs序

首先是看错题,再者是没想到交换两个序的顺序,真是太颓废了

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
int ans[200000],ab[200000],lo[200000],tail[200000],next[2000000],sora[2000000];
int ss,m1,n,m,b[2000000],l[2000000],r[2000000],h,u[200000],t; 
void origin()
{
	ss=n;
	for (int i=1;i<=n;i++) tail[i]=i,next[i]=0;
	for (m1=1;m1<=n+2;m1<<=1) ;
	for (int i=1;i<=m1+m1;i++) b[i]=0;
}
void link(int x,int y) 
{
	ss++,next[tail[x]]=ss,tail[x]=ss,sora[ss]=y,next[ss]=0;
}
void dfs(int x)
{
	l[x]=++h;
	for (int i=x,ne;next[i];) {
		i=next[i],ne=sora[i];
		dfs(ne);
	}
	r[x]=h;
}
bool cmp(int i,int j)
{
	return ab[i]>ab[j];
}
int max(int x,int y)
{
	return (lo[x]>lo[y]) ? x : y;
}
void change(int x,int y)
{
	x+=m1,b[x]=y;
	for (x>>=1;x;x>>=1) b[x]=max(b[x<<1],b[(x<<1)+1]);
}
int ask(int l,int r)
{
	l+=m1-1,r+=m1+1;
	int ans=0;
	for (;!((l^r)==1);l>>=1,r>>=1) {
		if ((l&1)==0) ans=max(ans,b[l^1]);
		if ((r&1)==1) ans=max(ans,b[r^1]);
	}
	return ans;
}
void init()
{
	int x; 
	scanf("%d%d\n",&n,&m);
	origin();
	for (int i=2;i<=n;i++) {
		scanf("%d%d%d\n",&x,&lo[i],&ab[i]);x++;
		link(x,i);
	}
	h=0;
	dfs(1);
	for (int i=2;i<=n;i++) u[i]=i;
	sort(u+2,u+n+1,cmp);
	lo[0]=-1; 
	for (int i=2,j=2;i<=n;i++) {
		for (;(j<=i) && (ab[u[j]]>ab[u[i]]);j++) change(l[u[j]],u[j]);
		ans[u[i]]=ask(l[u[i]],r[u[i]]);
	}
	for (int i=1;i<=m;i++) {
		scanf("%d\n",&x);x++;
		printf("%d\n",ans[x]-1);
	}
}
int main()
{
	freopen("input.txt","r",stdin);
	freopen("output.txt","w",stdout);
	cin>>t;
	for (;t;t--) init();
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值