这是一个句子测试

12
15
2015
0

Contest20151214滚粗记

听说这是JSOIDay5

膜了贵省的题目,感到不明觉厉。

条哥出去吔东西了,于是没有断网。

为了比赛公平,窝决定先泼会隔膜。

T1

这是一道好题。(然而窝不会做)

NiroBC将此题吊着打太强辣!!!

考虑三维容斥,即选i行j列k中颜色,表示i行j列可染可不染,另外n-i行和m-j列必定不染,k种颜色可用可不用,c-k种颜色必定不用。

那么答案就是

[tex]\sum\limits_{i = 0}^n {\sum\limits_{j = 0}^m {\sum\limits_{k = 0}^c {\mathop C\nolimits_n^i \mathop C\nolimits_m^j } } } \mathop C\nolimits_c^k {(k + 1)^{ij}}{( - 1)^{n + m + c - i - j - k}}[/tex]

于是n3枚举i、j、k就可以辣!(NiroBC还有一个不明觉厉的n2logn的做法)

T2

这是一道送分题。(其实是窝做过)

首先考虑这样一种暴力:枚举i,然后在前面找j,求出[j,i]的gcd。

那么可以优化,即已经知道了gcd[i,j],那么gcd[i,j+1]=gcd(a[j+1],gcd[i,j])。

显然会发现有许多gcd是相同的,那么对于后面就没用辣~

那么只要维护一下不同的gcd就能AC了。(虽然理论上是n2的但是卡它的数据太难出了Orz)

T3

这是一道恶心题。(其实是窝懒得写)

首先对于每一条地铁线路构一条新的路径,其中上站的边权为1,0,下站的边权为0,0,中途乘坐的边权为0,1。

那么只要让第一维边权最短的情况下第二维边权最长,跑最短路就可以辣!

然并卵Spfa被卡飞。。

于是可以先dijkstra处理第一维最短路,那么出现在最短路上的边一定构成了一个DAG。

那么就可以拓扑排序辣!

【Codes】

#include<cstdio>
#include<algorithm>
#include<cstring>
typedef long long ll;
using namespace std;
const int mod=1000000007;
int n,m,p,i,j,k;
ll ans;
ll c[410][410];
ll mi[410][160010];
int main(){
	scanf("%d%d%d",&n,&m,&p);
	c[0][0]=1;
	for (i=1;i<=max(n,max(m,p));i++){
		c[i][0]=1;
		for (j=1;j<=i;j++)c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;
	}
	for (i=1;i<=p+1;i++){
		mi[i][0]=1;
		for (j=1;j<=n*m;j++)mi[i][j]=mi[i][j-1]*i%mod;
	}
	for (i=0;i<=n;i++)
		for (j=0;j<=m;j++)
			for (k=0;k<=p;k++){
				ll tmp=c[n][i]*c[m][j]%mod*c[p][k]%mod*mi[k+1][i*j]%mod;
				if ((n+m+p-i-j-k)&1)ans=(ans-tmp+mod)%mod;else ans=(ans+tmp)%mod;
			}
	printf("%lld\n",ans);
}
#include<cstdio>
#include<algorithm>
#include<cstring>
typedef long long ll;
using namespace std;
const int M=200010;
int n,i,j,r;
ll ans;
ll a[M],h[M][2],q[M][2];
ll gcd(ll x,ll y){
	if (!(x%y))return y;else return gcd(y,x%y);
}
int main(){
	scanf("%d",&n);
	for (i=1;i<=n;i++){
		scanf("%lld",&a[i]);
		for (j=1;j<=r;j++)h[j][0]=gcd(h[j][0],a[i]);
		h[++r][0]=a[i],h[r][1]=i;
		int cnt=1;
		q[1][0]=h[1][0],q[1][1]=h[1][1];
		ans=max(ans,h[1][0]*(i-h[1][1]+1));
		for (j=2;j<=r;j++)
			if (h[j][0]!=h[j-1][0]){
				q[++cnt][0]=h[j][0],q[cnt][1]=h[j][1];
				ans=max(ans,h[j][0]*(i-h[j][1]+1));
			}
		r=cnt;
		for (j=1;j<=cnt;j++)h[j][0]=q[j][0],h[j][1]=q[j][1];
	}
	printf("%lld\n",ans);
}
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<vector>
#define fi first
#define se second
using namespace std;
typedef unsigned long long ull;
typedef pair<int,int> PII;
const int M=5000010;
const int inf=1000000007;
int n,m,i,j,y,st,ed,tmp,cnt,edgenum,Edgenum;
char s[50];
int head[M],vet[M],next[M],Head[M],Vet[M],Next[M],Len[M],init[M],dis[M],Dis[M],len[M][2],inq[M],x[M],q[M];
priority_queue<PII,vector<PII>,greater<PII> >Q;
pair<ull,int>a[M];
int solve(){
	ull tmp=0;
	for (int i=0;i<strlen(s);i++)tmp=tmp*2333+s[i];
	int ans=a[lower_bound(a+1,a+m+1,make_pair(tmp,0))-a].se;
	return ans;
}
void addedge(int x,int y,int p,int q){
	vet[++edgenum]=y;
	next[edgenum]=head[x];
	head[x]=edgenum;
	len[edgenum][0]=p;
	len[edgenum][1]=q;
}
void Addedge(int x,int y,int p){
	Vet[++Edgenum]=y;
	Next[Edgenum]=Head[x];
	Head[x]=Edgenum;
	Len[Edgenum]=p;
	init[y]++;
}
void dijkstra(){
	for (i=1;i<=cnt;i++)dis[i]=inf;
	Q.push(make_pair(0,st));dis[st]=0;
	for (i=1;i<=cnt;i++)inq[i]=0;
	while (!Q.empty()){
		int u=Q.top().se;Q.pop();
		if (inq[u])continue;
		inq[u]=1;
		for (int e=head[u];e;e=next[e]){
			int v=vet[e];
			if (dis[u]+len[e][0]<dis[v]){
				dis[v]=dis[u]+len[e][0];
				Q.push(make_pair(dis[v],v));
			}
		}
	}
}
int main(){
	scanf("%d%d",&n,&m);
	for (i=1;i<=m;i++){
		scanf("%s",s);
		for (j=0;j<strlen(s);j++)a[i].fi=a[i].fi*2333+s[j];
		a[i].se=i;
	}
	sort(a+1,a+m+1);
	cnt=m;
	for (i=1;i<=n;i++){
		scanf("%d",&tmp);
		scanf("%s",s);
		x[1]=solve();
		addedge(x[1],++cnt,1,0);
		for (j=2;j<=tmp;j++){
			scanf("%s",s);
			y=cnt,x[j]=solve();
			addedge(y,++cnt,0,1);
			addedge(x[j],cnt,1,0);
			addedge(cnt,x[j],0,0);
		}
		addedge(x[tmp],++cnt,1,0);
		for (j=tmp-1;j>=1;j--){
			y=cnt;
			addedge(y,++cnt,0,1);
			addedge(x[j],cnt,1,0);
			addedge(cnt,x[j],0,0);
		}
	}
	scanf("%s",s);
	st=solve();
	scanf("%s",s);
	ed=solve();
	dijkstra();
	for (i=1;i<=cnt;i++)
		for (int e=head[i];e;e=next[e])
			if (dis[i]+len[e][0]==dis[vet[e]])Addedge(i,vet[e],len[e][1]);
	int l=1,r=0;
	for (i=1;i<=cnt;i++)if (!init[i])q[++r]=i;
	while (l<=r){
		int u=q[l++];
		for (int e=Head[u];e;e=Next[e]){
			int v=Vet[e];
			init[v]--;
			if (init[v]==0)q[++r]=v;
		}
	}
	for (i=1;i<=cnt;i++){
		int u=q[i];
		for (int e=Head[u];e;e=Next[e]){
			int v=Vet[e];
			Dis[v]=max(Dis[v],Dis[u]+Len[e]);
		}
	}
	printf("%d\n%d\n",dis[ed],Dis[ed]);
}
Category: 蒟蒻的滚粗记 | Tags: | Read Count: 188

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

Host by is-Programmer.com | Power by Chito 1.3.3 beta | Theme: Aeros 2.0 by TheBuckmaker.com