Comet OJ - Contest #1

  A:随便怎么暴力。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define N 25
char getc(){char c=getchar();while (c!='.'&&c!='#') c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
	int x=0,f=1;char c=getchar();
	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
	while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
	return x*f;
}
int T,n,m;
char a[N][N];
signed main()
{
#ifndef ONLINE_JUDGE
	freopen("a.in","r",stdin);
	freopen("a.out","w",stdout);
#endif
	T=read();
	while (T--)
	{
		n=read(),m=read();
		for (int i=1;i<=n;i++)
			for (int j=1;j<=m;j++)
			a[i][j]=getc();
		int u=0,v=0;
		for (int i=1;i<=n;i++)
		{
			int cnt=0;
			for (int j=1;j<=m;j++)
			if (a[i][j]=='.') cnt++;
			if (cnt>v) u=i,v=cnt;
		}
		int l=0,r=0;
		for (int j=1;j<=m;j++)
		if (a[u][j]=='.') {l=j;break;}
		for (int j=m;j>=1;j--)
		if (a[u][j]=='.') {r=j;break;}
		cout<<(r-l)/2<<' '<<u<<' '<<(l+r)/2<<endl;
	}
	return 0;
	//NOTICE LONG LONG!!!!!
}

  B:显然选择单字符子串能形成n种不同的串。容易发现其他方案一定是由进位产生的,考虑固定某个9为子串右端点会产生多少种方案。数一下由其往前有多少个连续的9,这一段的每个后缀都会产生一种方案。然后再往前看一个数,若不为0答案再+1;若为0,由于所选串不能有前置0,需要找一下之前有没有非零数,若有则答案+1。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define N 200010
char getc(){char c=getchar();while (c!='.'&&c!='#') c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
	int x=0,f=1;char c=getchar();
	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
	while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
	return x*f;
}
char s[N];
signed main()
{
#ifndef ONLINE_JUDGE
	freopen("a.in","r",stdin);
	freopen("a.out","w",stdout);
#endif
	int T=read();
	while (T--)
	{
		scanf("%s",s+1);int n=strlen(s+1);
		ll ans=0;
		bool flag=0;int cnt=0;
		int first=n+1;for (int i=1;i<=n;i++) if (s[i]!='0') {first=i;break;}
		char last='0';
		for (int i=1;i<=n;i++)
		{
			if (s[i]!='9')
			{
				cnt=0,ans++;
				last=s[i];
			}
			else
			{
				cnt++;
				ans+=cnt;
				if (last=='0') ans+=i-cnt>first;
				else ans++;
			}
		}
		cout<<ans<<endl;
	}
	return 0;
	//NOTICE LONG LONG!!!!!
}

  C:状态尽量最小表示一下,哈希暴力记搜。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define N 200010
char getc(){char c=getchar();while (c!='.'&&c!='#') c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
	int x=0,f=1;char c=getchar();
	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
	while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
	return x*f;
}
int T,n;
struct data
{
	int x,y;
	bool operator <(const data&a) const
	{
		return x>a.x||x==a.x&&y>a.y;
	}
	bool operator ==(const data&a) const
	{
		return x==a.x&&y==a.y;
	}
}a[22];
map<ull,int> f;
ull calc(data *a)
{
	ull s=0;
	for (int i=0;i<=16;i++)
	s=s*13+a[i].x,s=s*17+a[i].y;
	return s;
}
int work(data *a)
{
	ull h=calc(a);
	if (f.find(h)!=f.end()) return f[h];
	bool flag=0;
	for (int i=1;i<=16;i++)
	if (a[i].x==0) break;
	else
	{
		if (i==a[0].x) continue;
		data b[22];
		for (int j=0;j<=16;j++) b[j]=a[j];
		a[i].x--;data c=a[i];swap(c.x,c.y);for (int j=1;j<=16;j++) swap(a[j].x,a[j].y);sort(a+1,a+17);
		for (int j=1;j<=16;j++) if (a[j]==c) {a[0].x=j;break;}
		int u=work(a);
		for (int j=0;j<=16;j++) a[j]=b[j];
		if (u==-1) return f[h]=1;
		if (u==0) flag=1;
	}
	if (flag) return f[h]=0;
	else return f[h]=-1;
}
signed main()
{
#ifndef ONLINE_JUDGE
	freopen("d.in","r",stdin);
	freopen("d.out","w",stdout);
#endif
	T=read();a[0].x=1;f[calc(a)]=0;
	while (T--)
	{
		n=read();
		for (int i=1;i<=20;i++) a[i].x=a[i].y=0;
		for (int i=1;i<=n;i++) a[read()].x++;
		for (int i=1;i<=n;i++) a[read()].y++;
		a[0].x=0;
		sort(a+1,a+21);
		int x=work(a);
		if (x==1) puts("AA wins");
		if (x==-1) puts("dreamoon wins");
		if (x==0) puts("Draw");
	}
	return 0;
	//NOTICE LONG LONG!!!!!
}

  D:大讨论大约是可以做的,但大约不是给人写的。考虑简单的做法。套路的将坐标系转45°,使菱形变为正方形,处理出二维前缀和。枚举正方形中心,二分半径,根据该正方形是否包含了所有没有草的点调整二分半径方向。然后判断该正方形中是否没有草,若是则更新答案。于是O(nmlog(n+m))。也可以做到线性,大概没啥本质区别。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 1010
#define mp(x,y) make_pair((x),(y))
char getc(){char c=getchar();while (c!='#'&&c!='.') c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
	int x=0,f=1;char c=getchar();
	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
	while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
	return x*f;
}
typedef pair<int,int> pii;
int T,n,m,a[N<<1][N<<1],s[N<<1][N<<1],s2[N<<1][N<<1];
pii trans(pii a){return mp(a.first+a.second,a.first-a.second+m);}
int calc(int x1,int y1,int x2,int y2)
{
	x1=max(x1,1),y1=max(y1,1);x2=min(x2,n+m),y2=min(y2,n+m);
	return s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1];
}
int calc2(int x1,int y1,int x2,int y2)
{
	x1=max(x1,1),y1=max(y1,1);x2=min(x2,n+m),y2=min(y2,n+m);
	return s2[x2][y2]-s2[x1-1][y2]-s2[x2][y1-1]+s2[x1-1][y1-1];
}
int main()
{
#ifndef ONLINE_JUDGE
	freopen("a.in","r",stdin);
	freopen("a.out","w",stdout);
	const char LL[]="%I64d\n";
#else
	const char LL[]="%lld\n";
#endif
	T=read();
	while (T--)
	{
		n=read(),m=read();
		int cnt=0;
		for (int i=1;i<=n+m;i++)
			for (int j=1;j<=n+m;j++)
			s[i][j]=s2[i][j]=0;
		for (int i=1;i<=n;i++)
			for (int j=1;j<=m;j++)
			{
				char c=getc();
				if (c=='#') a[i][j]=0;
				else a[i][j]=1;
				cnt+=a[i][j];
				s[i+j][i-j+m]=a[i][j];s2[i+j][i-j+m]=1-a[i][j];
			}
		for (int i=1;i<=n+m;i++)
			for (int j=1;j<=n+m;j++)
			s[i][j]+=s[i-1][j]+s[i][j-1]-s[i-1][j-1],
			s2[i][j]+=s2[i-1][j]+s2[i][j-1]-s2[i-1][j-1];
		int ansx=0,ansy=0,ansr=n+m+1;
		for (int i=1;i<=n;i++)
			for (int j=1;j<=m;j++)
			{
				int l=0,r=max(n,m),ans=n+m+1;
				pii t=trans(mp(i,j));
				while (l<=r)
				{
					int mid=l+r>>1;
					if (calc(t.first-mid,t.second-mid,t.first+mid,t.second+mid)==cnt) ans=mid,r=mid-1;
					else l=mid+1;
				}
				if (ans!=n+m+1&&calc(t.first-ans,t.second-ans,t.first+ans,t.second+ans)==cnt&&calc2(t.first-ans,t.second-ans,t.first+ans,t.second+ans)==0)
				if (ans<ansr||ans==ansr&&i<ansx||ans==ansr&&i==ansx&&j<ansy) ansx=i,ansy=j,ansr=ans;
			}
		if (ansr==n+m+1) printf("-1 -1 -1\n");
		else printf("%d %d %d\n",ansr,ansx,ansy);
	}
	return 0;
}

  E:对于牛的极长连续段,显然这些牛只能吃与其相邻的草,所以每一段牛互不相干可以分开考虑。对于一段牛,可能吃到的草的数量是牛的数量+1,找到这段里没被吃的草,以该位置将这段牛分成两半,然后只要保证两边的牛都不吃到该草即可。不妨设第一个位置是没被吃的草,容易发现不合法仅当某头向左走的牛移动时,其前方所有牛都已经吃过草。计算概率即可。注意虽然实际上其前方所有向右走的牛都已经吃过草就已经不合法了,但我们只应考虑该牛直接导致不合法的概率。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define P 998244353
#define N 200010
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
	int x=0,f=1;char c=getchar();
	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
	while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
	return x*f;
}
int T,n,inv[N];
char s[N];
signed main()
{
#ifndef ONLINE_JUDGE
	freopen("b.in","r",stdin);
	freopen("b.out","w",stdout);
#endif
	T=read();
	inv[0]=inv[1]=1;for (int i=2;i<=100001;i++) inv[i]=P-1ll*(P/i)*inv[P%i]%P;
	while (T--)
	{
		n=2*read()+1;int ans=1;
		scanf("%s",s+1);
		int cnt1=0,cnt2=0;
		for (int i=1;i<=n;i++)
		{
			if ((i&1)&&(s[i]=='.')) cnt1++;
			if (!(i&1)&&(s[i]=='L'||s[i]=='R')) ans=1ll*ans*(++cnt2)%P;
		}
		if (cnt1!=cnt2) ans=0;
		else
		for (int i=2;i<=n;i+=2)
		if (s[i]=='L'||s[i]=='R')
		{
			int t=i;
			while (t+2<=n&&s[t+2]!='.') t+=2;
			int cnt=0,pos=0;
			for (int j=i-1;j<=t+1;j+=2) 
			if (s[j]=='.') cnt++;else pos=j;
			if (cnt!=(t-i>>1)+1) {ans=0;break;}
			cnt=0;
			for (int j=pos-1;j>=i;j-=2)
			{
				if (s[j]!='L') ans=1ll*ans*cnt%P*inv[cnt+1]%P;
				cnt++;
			}
			cnt=0;
			for (int j=pos+1;j<=t;j+=2)
			{
				if (s[j]!='R') ans=1ll*ans*cnt%P*inv[cnt+1]%P;
				cnt++;
			}
			i=t;
		}
		printf("%d\n",ans);
	}
	return 0;
	//NOTICE LONG LONG!!!!!
}

  F:首先注意到合法欧拉序的任意子串都可以作为某合法欧拉序的前缀。所以随着左端点移动,可以作为欧拉序前缀的右端点单调不降。two pointers扫过去,过程中计算所有与左端点相同的点的贡献即可。

  判断一个序列是否是欧拉序显然用栈扫一遍即可。考虑将左端点移动一位的影响,可以发现对于树来说,是将根的第一个儿子提为根而将原来的根变为其最后一个儿子。于是维护的话把栈改为双端队列即可。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define N 1000010
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
	int x=0,f=1;char c=getchar();
	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
	while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
	return x*f;
}
int T,n,a[N],cnt[N],p[N];
ll s[N];
deque<int> q;
signed main()
{
#ifndef ONLINE_JUDGE
	freopen("b.in","r",stdin);
	freopen("b.out","w",stdout);
#endif
	T=read();
	while (T--)
	{
		n=read();ll ans=0;
		for (int i=1;i<=n;i++) a[i]=read(),p[i]=n+1;
		s[n+1]=cnt[n+1]=0;
		for (int i=1;i<=n;i++)
		{
			s[i]=s[p[a[i]]]+i;
			cnt[i]=cnt[p[a[i]]]+1;
			p[a[i]]=i;
		}
		for (int i=1;i<=n;i++) p[i]=0;q.clear();
		int r=0;
		for (int i=1;i<=n;i++)
		{
			if (i>1)
			{
				q.pop_front();
				if (p[a[i-1]]>=i)
				{
					if (!q.empty()&&q.front()==a[i]) q.pop_front();
					q.push_front(a[i-1]);
					q.push_front(a[i]);
				}
			}
			while (r<n)
			{
				if (p[a[r+1]]<i) q.push_back(a[++r]);
				else
				{
					int x=q.back();q.pop_back();
					if (q.empty()||q.back()!=a[r+1]) {q.push_back(x);break;}
					++r;
				}
				p[a[r]]=r;
			}
			ans+=s[p[a[i]]]-s[i]-1ll*(i-1)*(cnt[p[a[i]]]-cnt[i])+1;
		}
		cout<<ans<<endl;
	}
	return 0;
	//NOTICE LONG LONG!!!!!
}

 

  似乎有小裙子耶

posted @ 2019-04-18 21:18  Gloid  阅读(314)  评论(0编辑  收藏  举报