Codeforces Round #551 Div. 2

  A:签到。没仔细看数据范围,看到一个O(nt)的差点叉上去了。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define N 110
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 n,m,a[N],b[N];
signed main()
{
#ifndef ONLINE_JUDGE
	freopen("a.in","r",stdin);
	freopen("a.out","w",stdout);
#endif
	n=read(),m=read();
	int ans=1000000,ansi=0;
	for (int i=1;i<=n;i++)
	{
		a[i]=read(),b[i]=read();
		if (a[i]<m) a[i]+=b[i]*((m-a[i]-1)/b[i]+1);
		if (a[i]<ans) ans=a[i],ansi=i;
	}
	cout<<ansi;
	return 0;
	//NOTICE LONG LONG!!!!!
}

  B:从大到小考虑每个数,放在所有能放但还没有放的位置上即可。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define N 110
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 n,m,h,a[N],b[N],c[N][N],d[N][N]; 
signed main()
{
#ifndef ONLINE_JUDGE
	freopen("a.in","r",stdin);
	freopen("a.out","w",stdout);
#endif
	n=read(),m=read(),h=read();
	for (int i=1;i<=m;i++) b[i]=read();
	for (int i=1;i<=n;i++) a[i]=read();
	for (int i=1;i<=n;i++)
		for (int j=1;j<=m;j++)
		c[i][j]=read();
	for (int i=h;i>=1;i--)
		for (int x=1;x<=n;x++)
			for (int y=1;y<=m;y++)
			if (c[x][y]&&i<=a[x]&&i<=b[y]&&!d[x][y]) d[x][y]=i;
	for (int i=1;i<=n;i++)
	{
		for (int j=1;j<=m;j++)
		cout<<d[i][j]<<' ';
		cout<<endl;
	}
	return 0;
	//NOTICE LONG LONG!!!!!
}

  C:在右括号够的情况下尽量放左括号。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define N 300010
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 n,c[N][2];char s[N];
signed main()
{
#ifndef ONLINE_JUDGE
	freopen("a.in","r",stdin);
	freopen("a.out","w",stdout);
#endif
	n=read();
	scanf("%s",s+1);
	for (int i=n;i>=1;i--)
	{
		c[i][0]=c[i+1][0],c[i][1]=c[i+1][1];
		if (s[i]=='(') c[i][0]++;
		if (s[i]==')') c[i][1]++;
	}
	int cnt=0;
	for (int i=1;i<=n;i++)
	{
		if (s[i]=='(') cnt++;
		else if (s[i]==')') cnt--;
		else
		{
			if (n-i-c[i][0]<cnt+c[i][0]+1) s[i]=')',cnt--;
			else s[i]='(',cnt++;
		}
		if (cnt<0||cnt==0&&i<n) goto err;
	}
	if (cnt>0) goto err;
	printf("%s",s+1);
	return 0;
	err:cout<<":(";
	//NOTICE LONG LONG!!!!!
}

  D:这种东西容易想到二分答案,转化成01问题后,设f[i]为要让i号点为1其子树内至少有几个叶子为1,转移显然。dp完之后可以发现压根不需要二分答案。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define N 300010
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 n,a[N],b[N],p[N],f[N],fa[N],t,leaves;
struct data{int to,nxt;
}edge[N];
void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;}
void dfs(int k)
{
	for (int i=p[k];i;i=edge[i].nxt)
	dfs(edge[i].to);
	if (!p[k]) leaves++,f[k]=1;
	else
	if (a[k])
	{
		f[k]=N;
		for (int i=p[k];i;i=edge[i].nxt)
		f[k]=min(f[k],f[edge[i].to]);
	}
	else
	{ 
		f[k]=0;
		for (int i=p[k];i;i=edge[i].nxt)
		f[k]+=f[edge[i].to];
	}
}
signed main()
{
#ifndef ONLINE_JUDGE
	freopen("a.in","r",stdin);
	freopen("a.out","w",stdout);
#endif
	n=read();
	for (int i=1;i<=n;i++) a[i]=read();
	for (int i=2;i<=n;i++)
	{
		fa[i]=read();
		addedge(fa[i],i);
	}
	dfs(1);
	cout<<leaves-f[1]+1;
	return 0;
	err:cout<<":(";
	//NOTICE LONG LONG!!!!!
}

  E:询问每一行,考虑其答案的奇偶性,若有奇数,一定有两行均为奇数,头和尾就在这两行内;若没有奇数,说明头和尾在同一行,再询问每一列找到在哪两列即可。确定行/列后直接二分即可。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define N 1010
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 n;
signed main()
{
	n=read();
	int x=0,y=0;
	for (int i=1;i<=n;i++)
	{
		if (x==0&&i==n) break;
		cout<<'?'<<' '<<i<<' '<<1<<' '<<i<<' '<<n<<endl;
		int u=read();
		if (u&1) if (x) y=i;else x=i;
	}
	if (!x)
	{
		int ansx[3],ansy[3],cnt=0;
		for (int i=1;i<=n;i++)
		{
			cout<<'?'<<' '<<1<<' '<<i<<' '<<n<<' '<<i<<endl;
			int u=read();
			if (u&1)
			{
				int l=1,r=n;
				while (l<r)
				{
					int mid=l+r>>1;
					cout<<"?"<<' '<<l<<' '<<i<<' '<<mid<<' '<<i<<endl;
					int u=read();
					if (u&1) r=mid;
					else l=mid+1;
				}
				cnt++;ansx[cnt]=l,ansy[cnt]=i;
			}
		}
		cout<<"!"; 
		for (int i=1;i<=cnt;i++) cout<<' '<<ansx[i]<<' '<<ansy[i];
	}
	else
	{
		int ansx[3],ansy[3],cnt=0;
		int i=x;
		int l=1,r=n;
		while (l<r)
		{
			int mid=l+r>>1;
			cout<<"?"<<' '<<i<<' '<<l<<' '<<i<<' '<<mid<<endl;
			int u=read();
			if (u&1) r=mid;
			else l=mid+1;
		}
		cnt++;ansx[cnt]=i,ansy[cnt]=l;
		i=y;
		l=1,r=n;
		while (l<r)
		{
			int mid=l+r>>1;
			cout<<"?"<<' '<<i<<' '<<l<<' '<<i<<' '<<mid<<endl;
			int u=read();
			if (u&1) r=mid;
			else l=mid+1;
		}
		cnt++;ansx[cnt]=i,ansy[cnt]=l;
		cout<<"!"; 
		for (int i=1;i<=cnt;i++) cout<<' '<<ansx[i]<<' '<<ansy[i];
	}
	return 0;
	//NOTICE LONG LONG!!!!!
}

  F:不妨设总长度为1,最后再乘l即可。考虑坐标为i的点的贡献,其被k条线段覆盖的概率是C(n,k)pn-k(1-p)k,其中p=i2+(1-i)2=2i2-2i+1。对每个k暴力积分即可,直接暴力进行多项式运算。可能略卡常。场上居然以为积分求逆元要带log,自闭了。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define N 2010
#define P 998244353
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 n,k,l,ans,C[N][N],f[N<<1],h[N<<1],Inv[N<<1],g[N];
int ksm(int a,int k)
{
	int s=1;
	for (;k;k>>=1,a=1ll*a*a%P) if (k&1) s=1ll*s*a%P;
	return s;
}
int inv(int a){return ksm(a,P-2);}
void inc(int &x,int y){x+=y;if (x>=P) x-=P;}
void mul(int m,int *f,int *g,int n)
{
	memset(h,0,sizeof(h));
	for (int i=0;i<=m;i++)
		for (int j=0;j<min(i+1,n);j++)
		inc(h[i],1ll*f[i-j]*g[j]%P);
	for (int i=0;i<=m;i++) f[i]=h[i];
}
void div(int m,int *f,int *g,int n)
{
	h[2]=f[m],h[1]=f[m-1];f[m]=f[m-1]=0;
	int x=inv(g[2]);
	for (int i=m-2;i>=0;i--)
	{
		h[0]=f[i];
		f[i]=1ll*h[2]*x%P;
		h[2]=(h[1]+P-1ll*g[1]*f[i]%P)%P;
		h[1]=(h[0]+P-1ll*g[0]*f[i]%P)%P;
	}
}
int calc()
{
	int s=0;
	for (int i=1;i<=n*2+1;i++) inc(s,1ll*f[i-1]*Inv[i]%P);
	return s;
}
signed main()
{
	n=read(),k=read(),l=read();
	C[0][0]=1;
	for (int i=1;i<=n;i++)
	{
		C[i][0]=1;
		for (int j=1;j<=i;j++)
		C[i][j]=(C[i-1][j]+C[i-1][j-1])%P;
	}
	Inv[0]=Inv[1]=1;for (int i=2;i<=n*2+4;i++) Inv[i]=P-1ll*(P/i)*Inv[P%i]%P;
	f[0]=1;
	g[0]=0,g[1]=2,g[2]=P-2;
	for (int i=1;i<=k;i++) mul(i*2,f,g,3);
	g[0]=1,g[1]=P-2,g[2]=2;
	for (int i=1;i<=n-k;i++) mul((i+k)*2,f,g,3);
	inc(ans,1ll*C[n][k]*calc()%P);
	for (int i=k+1;i<=n;i++)
	{
		g[0]=1,g[1]=P-2,g[2]=2;
		div(n*2,f,g,3);
		g[0]=0,g[1]=2,g[2]=P-2;
		mul(n*2,f,g,3);
		inc(ans,1ll*C[n][i]*calc()%P);
	}
	ans=1ll*ans*l%P;
	cout<<ans;
	return 0;
	//NOTICE LONG LONG!!!!!
}
 

  小小号打的。result:rank 27 rating +222

posted @ 2019-04-14 12:37  Gloid  阅读(398)  评论(0编辑  收藏  举报