2021牛客OI赛前集训营-提高组(第二场)

链接

vp 的,赛时 \(80+0+100+0\)

T1 不会,写了个分块+ST 表,发现常数还比暴力大。

T2 不会,看题解才会了,想到了经典套路之固定端点瞎选。

T3 萌萌数据结构,提示性挺强的,发现每个点都可以将 2 段序列合并成一段新的,考虑贪心即可,每次合并 2 段最大的序列,考虑 multiset+启发式合并,优秀的 \(O(n\log^2n)\)

T4 弃了。

赛后:

T1 发现交换没影响,因为如果 2 个位,考虑交换。

若原来贡献为 1,交换后也显然贡献为 1。

若原来贡献为 2,交换后贡献为 0。

若原来贡献为 0,交换后贡献为 2。

发现都对奇偶性没影响,考虑记录下区间 1 的数量即可。

T2

我们可以考虑固定一条线段看看能不能乱选。

考虑 2 个点 \(A(x,y),B(xx,yy)\)

如何求出线段 \(AB\) 上的整点数量。

\(a=|x-xx|,b=|y-yy|\),答案显然是 \(\gcd(a,b)\),参考什么莫反的题。

把整一段拍扁到序列上,发现 \(D\) 的限制并不是很好做,但是考虑单位相隔长度一样,即每个点和它的横坐标加 1 的那个点的距离都是一样的。

\(dis=dist((0,0),(\dfrac{a}{\gcd(a,b)},\dfrac{b}{\gcd(a,b)}))\)

那么假如选了 0 和第 \(qwq\) 个点,合法当且仅当

\[qwq*dis\ge D,qwq\ge\dfrac{D}{dis} \]

\(qwq=\lceil\dfrac{D}{dis}\rceil\)

考虑只需要选 \(N-2\) 个点了,因为左右端点都选了。

那么答案为

\[C(gcd(a,b)-1-(qwq-1)*(N-1),N-2) \]

\(-(qwq-1)*(N-1)\)\(N\) 个点,间隔 \(N-1\),每个间隔至少 \(qwq-1\)

最后考虑乘上答案系数,注意假如是不是水平/竖直线需要 \(\times2\),因为有序点对。

T1

#include <cstdio>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <set>
#include <bitset>
#include <cmath>
using namespace std;

int rd() {
	char ch=getchar(); int sum=0,f=1;
	while(ch>'9'||ch<'0') {
		if(ch=='-') f=-1; ch=getchar();
	}
	while(ch<='9'&&ch>='0') sum=sum*10+ch-'0',ch=getchar();
	return sum*f;
}

#define N (int)(2e5+3)
#define M 402
int n,m,Q;

bool gt() {
	char ch=getchar();
	while(ch!='0'&&ch!='1') ch=getchar();
	return ch-'0';
}

struct BBB {
	bitset<N>B[20][M]; 
	int len,bl,id[N],L[M],R[M]; bool a[N];	
	void init(int lenn) {
		len=lenn; bl=min(len,500);
		for(int i=1;i<=len;i++) {
			a[i]=gt(); id[i]=(i-1)/bl+1;
			B[0][id[i]][i]=a[i];
		}
		for(int i=1;i<=id[len];i++) L[i]=(i-1)*bl+1,R[i]=i*bl; R[id[len]]=len;
		for(int i=1;(1ll<<i)<=id[len];i++) {
			for(int j=1;j+(1ll<<i)-1<=id[len];j++) {
				B[i][j]=(B[i-1][j]|B[i-1][j+(1ll<<(i-1))]);
			}
		}
	}
	void get(int l,int r,bitset<N>&BT) {
	//	cout<<id[l]<<" "<<id[r]<<endl;
		if(id[l]==id[r]) {
			for(int i=l;i<=r;i++) {
				if(a[i]) BT[i-l+1]=1;
			}
		} else {
		//	cout<<l<<" "<<R[id[l]]<<" "<<L[id[r]]<<" "<<r<<endl;
			for(int i=l;i<=R[id[l]];i++) if(a[i]) BT[i-l+1]=1;
			for(int i=L[id[r]];i<=r;i++) if(a[i]) BT[i-l+1]=1;
			int x=id[l]+1,y=id[r]-1; if(x>y) return ;
			int qwq=log2(y-x+1);
			BT|=(B[qwq][x]>>(l-1)); BT|=(B[qwq][y-(1ll<<qwq)+1]>>(l-1));
		}
	}
}P1,P2;
bitset<N>r1,r2;

namespace xgf{
	int a[N],b[N];
	void solve() {
		for(int i=1;i<=n;i++) a[i]=gt();
		for(int i=1;i<=m;i++) b[i]=gt();
		Q=rd();
		int l,r,ll,rr;
		while(Q--) {
			l=rd(); r=rd(); ll=rd(); rr=rd(); int qwq=0;
			for(int i=0;i<r-l+1;i++) if(a[l+i]!=b[ll+i]) ++qwq;
			if(qwq&1) puts("1"); else puts("0");
		}
	}
}

int main() {
//	freopen("string2.in","r",stdin); freopen("qwq.out","w",stdout);
	n=rd(); m=rd();
	if(n<=(int)(5e4)) {
		xgf::solve(); return 0;
	}
	P1.init(n); P2.init(m);// P1.DE();
	Q=rd(); int l,r,ll,rr; 
	while(Q--) {
		l=rd(); r=rd(); ll=rd(); rr=rd();
		r1.reset(); r2.reset(); P1.get(l,r,r1); P2.get(ll,rr,r2);
	/*	for(int i=0;i<r-l+1;i++) cout<<r1[i]; puts("");
		for(int i=0;i<r-l+1;i++) cout<<r2[i]; puts("");
	*/	
		int qwq=(r1^r2).count(); //cout<<qwq<<endl;
		if(qwq&1) puts("1"); else puts("0");
	}
	return 0;
}

T2

#include <cstdio>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <set>
#include <bitset>
#include <cmath>

#define ll long long
#define mod (int)(1e9+7)
using namespace std;

int rd() {
	char ch=getchar(); int sum=0,f=1;
	while(ch>'9'||ch<'0') {
		if(ch=='-') f=-1; ch=getchar();
	}
	while(ch<='9'&&ch>='0') sum=sum*10+ch-'0',ch=getchar();
	return sum*f;
}

ll lrd() {
	char ch=getchar(); ll sum=0,f=1;
	while(ch>'9'||ch<'0') {
		if(ch=='-') f=-1; ch=getchar();
	}
	while(ch<='9'&&ch>='0') sum=sum*10+ch-'0',ch=getchar();
	return sum*f;
}

ll C[2003][2003];
ll N,W,H,D;

ll fpow(ll x,ll y) {
	ll res=1; x%=mod;
	while(y) {
		if(y&1) res=res*x%mod; y>>=1; x=x*x%mod;
	}
	return res;
}

ll gcd(ll x,ll y) {
	return !y?x:gcd(y,x%y);
}

double dis(ll x,ll y,ll xx,ll yy) {
	return sqrt(1.0*(x-xx)*(x-xx)+1.0*(y-yy)*(y-yy));
}

ll CC(ll x,ll y) {
	if(x<y||y<0) return 0;
	return C[x][y];
}

ll work(ll x,ll y) {
	if(x==0&&y==0) return 0;
	ll d=gcd(x,y);
	ll k=ceil(D/dis(0,0,x/d,y/d));
	int qwq=CC(d-1-(N-1)*(k-1),N-2);
	if(x!=0&&y!=0) qwq=qwq*2ll%mod; // (x1,y1) (x2,y2) 倒过来
	return qwq; 
}

void solve() {
	N=lrd(); W=lrd(); H=lrd(); D=lrd(); ll ans=0;
	if(N==1) {
		printf("%lld\n",(W+1)*(H+1)); return ;
	}
	for(int i=0;i<=W;i++) {
		for(int j=0;j<=H;j++) ans=(ans+(W-i+1)*(H-j+1)%mod*work(i,j)%mod)%mod;
	}
	ans=(ans%mod+mod)%mod;
	printf("%lld\n",ans);
}

int main() {
	C[0][0]=1;
	for(int i=1;i<=2000;i++) {
		C[i][0]=1; for(int j=1;j<=i;j++) C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;
	}
	int T=rd(); while(T--) solve(); return 0;
}

T3

#include <cstdio>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <set>

using namespace std;

int rd() {
	char ch=getchar(); int sum=0,f=1;
	while(ch>'9'||ch<'0') {
		if(ch=='-') f=-1; ch=getchar();
	}
	while(ch<='9'&&ch>='0') sum=sum*10+ch-'0',ch=getchar();
	return sum*f;
}

#define N (int)(1e5+5)
struct edge {
	int nex,to;
}e[N<<1];
multiset<int,greater<int> >s[N];
multiset<int>::iterator it;
int head[N],cnt,id[N],n;

void add_edge(int x,int y) {
	e[++cnt].nex=head[x]; e[cnt].to=y; head[x]=cnt;
}

void dfs1(int x,int ff) {
	for(int i=head[x];i;i=e[i].nex) {
		int y=e[i].to; if(y==ff) continue;
		dfs1(y,x);
		if(s[id[y]].size()>s[id[x]].size()) swap(id[x],id[y]);
		for(it=s[id[y]].begin();it!=s[id[y]].end();it++) s[id[x]].insert(*it);
		s[id[y]].clear();
	}
	if(!s[id[x]].size()) s[id[x]].insert(1);
	else if(s[id[x]].size()==1) {
		it=s[id[x]].begin(); s[id[x]].insert(*it+1); s[id[x]].erase(it);
	} else {
		int qwq=1; it=s[id[x]].begin(); qwq+=*it; s[id[x]].erase(it); it=s[id[x]].begin(); qwq+=*it; s[id[x]].erase(it);
		s[id[x]].insert(qwq);
	}
}

void solve() {
	n=rd(); cnt=0; memset(head,0,sizeof(head)); 
	for(int i=1;i<=n;i++) {
		id[i]=i; s[i].clear();
	}
	int x,y;
	for(int i=1;i<n;i++) x=rd(),y=rd(),add_edge(x,y),add_edge(y,x);
	dfs1(1,0); printf("%d\n",*s[id[1]].begin());
}

int main() {
	//freopen("qwq.out","w",stdout);
	int T=rd(); while(T--) solve(); return 0;
}
posted @ 2022-02-08 18:08  FxorG  阅读(75)  评论(0编辑  收藏  举报