2018.7.23模拟赛

T1:
2000的数据显然不能矩阵乘法。
考场上忘了矩阵乘法怎么写了,手推了一下,结果突然发现有公因式Orz
提取一下公因式,就可以有O(nm)的解法了。。。(忘了矩乘海星)

#include <iostream>
#include <cstdio>
#include <cctype>
#include <cstring>
using namespace std;
const int N=2005;
int n,m,a[N][N],b[N][N];
long long s1[N][N],s2[N][N];
int xa,xb,ya,yb;
long long ans;
int rd() {
	int x=0,f=1;char ch=getchar();
	while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
	while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
int main() {
	freopen("matrix.in","r",stdin);
	freopen("matrix.out","w",stdout);
	n=rd(),m=rd();
	for(int i=1;i<=n;i++) 
		for(int j=1;j<=n;j++)
			a[i][j]=rd();
	for(int i=1;i<=n;i++) 
		for(int j=1;j<=n;j++)
			b[i][j]=rd();
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			s1[i][j]=s1[i-1][j]+a[i][j];
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			s2[i][j]=s2[i][j-1]+b[i][j];
	
	while(m--) {
		ans=0ll;
		xa=rd(),ya=rd(),xb=rd(),yb=rd();
		if(xa>xb) swap(xa,xb);
		if(ya>yb) swap(ya,yb);
		for(int i=1;i<=n;i++) {
			ans+=(s1[xb][i]-s1[xa-1][i])*(s2[i][yb]-s2[i][ya-1]);
		}
		cout<<ans<<endl;
	}
	return 0;
}

T2:
有个结论:选的点的x,y坐标一定出现过。(富贵险中求,和暴力拍一下发现对的。。。)

#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <cstdio>
#include <cctype>
#include <cstring>
using namespace std;
vector<long long>x,y;
long long rd() {
	long long x=0,f=1;char ch=getchar();
	while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
	while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
const int N=55;
long long n,dis[N],ans[N],sum[N];
struct Points {long long x,y;} p[N];
int main() {
	freopen("tower.in","r",stdin);
	freopen("tower.out","w",stdout);
	n=rd();
	memset(ans,0x3f,sizeof ans);
	for(int i=1; i<=n; i++) p[i].x=rd(),p[i].y=rd(),x.push_back(p[i].x),y.push_back(p[i].y);
	for(int i=0; i<x.size(); i++) 
		for(int j=0; j<y.size(); j++) {
			memset(dis,0x3f,sizeof dis);
			for(int k=1; k<=n; k++) dis[k]=min(dis[k],abs(p[k].x-x[i])+abs(p[k].y-y[j]));
			sort(dis+1,dis+1+n);
			for(int k=1;k<=n;k++) sum[k]=sum[k-1]+dis[k];
			for(int k=1;k<=n;k++) ans[k]=min(ans[k],sum[k]);
		}
	for(int i=1;i<=n;i++) printf("%lld
",ans[i]);
	return 0;
}

T3
树形dp,f[x][0]表示不选这个点作为起点的最大匹配,对应一个g[x][0]表示方案数,f[x][1]表示取这个点为起点。
转移的时候取最大匹配及对应的方案即可。需要注意的是如果f[x][0]==f[x][1],g需要加法原理求和。(需要写高精)
日常想骂出高精的出题人...

#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <cstdio>
#include <cctype>
#include <cstring>
#define int long long
#define f(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int N=1005;
int n,m,head[N],ecnt;
int f[N][2],mxf[N],g[N][2],mxg[N];
struct Edge {
	int nxt,to;
} e[N<<1];
void add(int bg,int ed) {
	e[++ecnt].nxt=head[bg];
	e[ecnt].to=ed;
	head[bg]=ecnt;
}
void dfs(int x,int fa) {
	g[x][0]=1;
	for(int i=head[x]; i; i=e[i].nxt) {
		int v=e[i].to;
		if(v==fa) continue;
		dfs(v,x);
		f[x][0]+=mxf[v];
		g[x][0]=g[x][0]*mxg[v];
	}
	int t=0;int p=0;
	for(int i=head[x]; i; i=e[i].nxt) {
		int v=e[i].to;
		if(v==fa) continue;
		t=f[x][0]-mxf[v]+f[v][0]+1;
		p=g[x][0]/mxg[v]*g[v][0];
		if(f[x][1]==t) g[x][1]+=p;
		else if(f[x][1]<t) g[x][1]=p,f[x][1]=t;
	}
	if(f[x][0]>f[x][1]) mxf[x]=f[x][0],mxg[x]=g[x][0];
	else if(f[x][1]>f[x][0]) mxf[x]=f[x][1],mxg[x]=g[x][1];
	else mxf[x]=f[x][1],mxg[x]=g[x][1]+g[x][0];
}
signed main() {
	freopen("tree.in","r",stdin);
	freopen("tree.out","w",stdout);
	scanf("%lld",&n);
	for(int i=1,p,c,a; i<=n; i++) {
		scanf("%lld%lld",&p,&c);
		for(int j=1; j<=c; j++) {
			scanf("%lld",&a);
			add(p,a);
			add(a,p);
		}
	}
	dfs(1,0);
	cout<<mxf[1]<<endl<<mxg[1];
}
我是咸鱼。转载博客请征得博主同意Orz
原文地址:https://www.cnblogs.com/sdfzhsz/p/9355348.html