ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

21牛客多校第五场

2021-08-02 12:04:33  阅读:155  来源: 互联网

标签:ch 21 int 第五场 rep long 牛客 MOD define


A

圆方树 咕

B

显然开盒子的顺序应按照\(w\)升序,而\(hint\)若选择使用应该在一开始就使用

在使用\(hint\)的情况下,因为知道\(01\)的总数,每种情况应当在最后一段连续的\(0/1\)前终止

即\(100\cdots 0\)此类情况,在\(0\)处截止,其花费为\(sum_i\)即到\(0\)处\(w\)的前缀和

而此类情况的概率为后\(n-i\)一样且第\(i\)个不同,\(p=\frac{2}{2^{n-i+1}}=\frac{1}{2^{n-i}}\)

最后比较使用\(hint\)的答案与暴力全开哪个较小

#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 100100
#define MOD 998244353
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pls(a,b) (a+b)%MOD
#define mns(a,b) (a-(b)+MOD)%MOD
#define mul(a,b) (1LL*(a)*(b))%MOD
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline int read()
{
    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 n;db x,w[MAXN],ans;
int main()
{
	n=read();scanf("%lf",&x);
	rep(i,1,n) scanf("%lf",&w[i]);
	sort(w+1,w+n+1);rep(i,1,n) w[i]+=w[i-1];
	db pw=0.5;
	dwn(i,n-1,1) ans+=w[i]*pw,pw*=0.5;
	ans=min(ans+x,w[n]);
	printf("%.7lf\n",ans);
}

C

由于调和级数,需要\(O(1)\)查询对\(i=t\)的情况终止点在哪里

考虑先预处理每个位置的\(W,L\)前缀和以及每个\(W,L\)位置,这样可以找到从位置\(x\)开始后先到\(i\)球的位置

若此时\(W,L\)的差\(>1\)则显然胜负已分,否则需要处理一个从每个点开始何时破局,设为\(nxt_x\)

对位置\(x\)来说,若接下来是两球不同,则仍然是平局,\(nxt_x=nxt_{x+2}\);否则在\(x+1\)时刻该局结束

预处理完毕后模拟

#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 1001001
#define MOD 998244353
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pls(a,b) (a+b)%MOD
#define mns(a,b) (a-(b)+MOD)%MOD
#define mul(a,b) (1LL*(a)*(b))%MOD
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline int read()
{
    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 n,cnt[MAXN][2],pos[MAXN][2],nxt[MAXN],ans;
char s[MAXN];
int main()
{
	n=read();scanf("%s",s+1);
	rep(i,1,n)
	{
		rep(j,0,1) cnt[i][j]=cnt[i-1][j];
		if(s[i]=='L') pos[++cnt[i][0]][0]=i;
		else pos[++cnt[i][1]][1]=i;
	}
	nxt[n]=nxt[n+1]=n+1;
	dwn(i,n-1,1) nxt[i]= s[i]==s[i+1]?i+1:nxt[i+2];
	int p1,p2,p,c1,c2,pw=1,res;
	rep(t,1,n)
	{
		res=0;rep(i,0,n)
		{
			p1=p2=n+1;
			if(cnt[i][0]+t<=cnt[n][0]) p1=pos[cnt[i][0]+t][0];
			if(cnt[i][1]+t<=cnt[n][1]) p2=pos[cnt[i][1]+t][1];
			p=min(p1,p2);if(p==n+1) break;
			c1=cnt[p][0]-cnt[i][0],c2=cnt[p][1]-cnt[i][1];
			if(abs(c1-c2)==1) p=nxt[p];
			if(p==n+1) break;
			c1=cnt[p][0]-cnt[i][0],c2=cnt[p][1]-cnt[i][1];
			res+=(c1<c2);i=p-1;
		}
		ans=pls(ans,mul(res,pw)),pw=mul(pw,n+1);
	}
	printf("%d\n",ans);
}

D

可以在每次找到一对相同\(a_i=b_j\)时统计答案,设\(f[i][j]\)表示前面范围内以\(i,j\)结尾的公共子序列个数,\(g[i][j]\)表示后面范围内符合条件的点对个数

\(f[i][j]\)简单\(dp\)即可,\(g[i][j]\)的计算过程中,每次找到一对符合答案的\(a_i<b_j\)需要\(+\sum\limits_{i=0}^{min(x,y)} \binom{x}{i}\binom{y}{i}\)这样的东西

不妨令\(x\le y\) 有\(\sum\limits_{i=0}^{x} \binom{x}{i}\binom{y}{i}=\sum\limits_{i=0}^{x} \binom{x}{x-i}\binom{y}{i}=\sum\limits_{i=0}^{x} \binom{x+y}{x}\)

预处理阶乘后直接\(dp\)

#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 100100
#define MOD 1000000007
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pls(a,b) (a+b)%MOD
#define mns(a,b) (a-(b)+MOD)%MOD
#define mul(a,b) (1LL*(a)*(b))%MOD
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline int read()
{
    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 n,m,dp[5050][5050],f[5050][5050];
int fac[MAXN],ifac[MAXN],ans;
char a[5050],b[5050];
int qp(int x,int t,int res=1)
{
	for(;t;t>>=1,x=mul(x,x)) if(t&1) res=mul(res,x);
	return res;
}
#define inv(x) qp(x,MOD-2)
int C(int n,int m)
{
	return mul(fac[n],mul(ifac[n-m],ifac[m]));
}
int main()
{
	scanf("%s%s",a+1,b+1);n=strlen(a+1),m=strlen(b+1);
	ifac[0]=fac[0]=1;rep(i,1,1e4+10) fac[i]=mul(fac[i-1],i),ifac[i]=inv(fac[i]);
	dwn(i,n,1) dwn(j,m,1)
	{
		f[i][j]=mns(pls(f[i][j+1],f[i+1][j]),f[i+1][j+1]);
		if(a[i]<b[j]) f[i][j]=pls(f[i][j],C(m-j+n-i,m-j));
	}
	ans=f[1][1];
	rep(i,1,n) rep(j,1,m) 
	{
		if(a[i]==b[j])
		{
			  dp[i][j]=pls(dp[i-1][j-1],1);
			ans=pls(ans,mul(dp[i][j],f[i+1][j+1]));
		}
		dp[i][j]=pls(mns(pls(dp[i-1][j],dp[i][j-1]),dp[i-1][j-1]),dp[i][j]);
	}
	printf("%d\n",ans);
}

E

树\(dp\) 咕

F

三分套三分 咕

G

设\(F_S\)表示该位为\(1\)的质因数取满其余随意组合出的数和\(a\)的最小差,\(G_S\)表示和\(b\)的差,答案即为所有\(F_{i}+G_{U-i}\)取\(min\)

而搜索的时候可以搜索出: 该位为\(1\)的质因数取满其余不取满组合出的数和\(a\)的最小差,记为\(f_S\)

令\(F=f\),\(F_S\)可以更新所有\(F_{S-(1<<j)}\),\(O(n2^n)\)计算出所有\(F\),\(G\)同理

最后统计答案

#include<bits/stdc++.h>
#define inf 2139062143
#define ll __int128
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 100100
#define MOD 998244353
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pls(a,b) (a+b)%MOD
#define mns(a,b) (a-(b)+MOD)%MOD
#define mul(a,b) (1LL*(a)*(b))%MOD
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline ll read()
{
    ll 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;
}
void write(ll x)
{
	int st[40],tp=0;
	if(!x) {putchar('0');return ;}
	while(x) st[++tp]=x%10,x/=10;
	while(tp) putchar(st[tp--]+'0');
}
int n;ll w[20],tot[20],a,b;
ll f[1<<18],g[1<<18],ans;
void dfs(int x,int st,ll now)
{
	if(x==n+1) 
	{
		if(now>=a) f[st]=min(f[st],now-a);
		if(now>=b) g[st]=min(g[st],now-b);
		return ;
	}
	dfs(x+1,st,now);
	rep(i,1,tot[x]-1) {now*=w[x];dfs(x+1,st,now);}
	now*=w[x],st|=(1<<x-1);dfs(x+1,st,now);
}
int main()
{
	n=read();rep(i,1,n) w[i]=read(),tot[i]=read();
	a=read(),b=read(),ans=1;
	int mxs=(1<<n)-1;rep(i,1,33) ans=ans*10;
	rep(i,0,mxs) f[i]=g[i]=ans;dfs(1,0,1);
	dwn(i,mxs,0) rep(j,0,n-1) if(!((i>>j)&1))
		f[i]=min(f[i|(1<<j)],f[i]),g[i]=min(g[i|(1<<j)],g[i]);
	rep(i,0,mxs) ans=min(ans,f[i]+g[mxs^i]);
	write(ans);
}

H

考虑如下形式的矩阵,在任何情况下均满足条件:

\[\begin{pmatrix} 0&1&0&1&0&\cdots\\ 0&1&0&1&0&\cdots\\ 1&0&1&0&1&\cdots\\ 1&0&1&0&1&\cdots\\ \vdots&\vdots&\vdots&\vdots&\vdots&\ddots \end{pmatrix} \]

#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 100100
#define MOD 998244353
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pls(a,b) (a+b)%MOD
#define mns(a,b) (a-(b)+MOD)%MOD
#define mul(a,b) (1LL*(a)*(b))%MOD
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline int read()
{
    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 n,m; 
int main()
{
	n=read(),m=read();
	rep(i,0,n-1) {rep(j,0,m-1) printf("%d",(i/2+j)&1);puts("");}
}

I

还挺裸的回滚莫队,用链表维护一下每个区间的左右端点,每次更新答案总复杂度\(O(n\sqrt{n}+k)\)

回滚莫队时可以把一个更改操作的指针和值一起放到\(vector\)里,写起来非常方便

#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 100100
#define MOD 998244353
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pls(a,b) (a+b)%MOD
#define mns(a,b) (a-(b)+MOD)%MOD
#define mul(a,b) (1LL*(a)*(b))%MOD
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline int read()
{
    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;
}
inline void inc(int &x,int y){x=pls(x,y);}
int n,Q,sz,g[MAXN],bl[MAXN],ans[MAXN],cnt[MAXN],res,l[MAXN],r[MAXN];
vector<pair<int*,int> > opt;
struct Ask{int id,l,r,k;}q[MAXN];
bool operator < (Ask &a,Ask &b){return bl[a.l]==bl[b.l]?a.r<b.r:a.l<b.l;}
inline void mdf(int *x,int w){opt.pb({x,*x});*x=w;}
inline void add(int x)
{
	if(cnt[g[x]]) return ;x=g[x];mdf(&cnt[x],1);
	//cout<<"add: "<<x<<endl;
	int pre=l[x-1],suf=r[x+1];
	if(pre==-1) pre=x;if(suf==-1) suf=x;
	mdf(&r[pre],suf);mdf(&l[suf],pre);
	if(suf-pre+1>res) mdf(&res,suf-pre+1);
}
void del(int t)
{
	while(opt.size()>t)
		{*opt.back().fi=opt.back().se;opt.pop_back();}
}
int main()
{
	n=read(),Q=read(),sz=sqrt(n+5);Fill(l,0xff);Fill(r,0xff);
	rep(i,1,n) g[i]=read(),bl[i]=i/sz;
	rep(i,1,Q) q[i].l=read(),q[i].r=read(),q[i].k=read()-1,q[i].id=i;
	sort(q+1,q+Q+1);int ed,pos,tag,pw;
	rep(i,1,Q)
	{
		if(i==1||bl[q[i].l]!=bl[q[i-1].l])
			{ed=bl[q[i].l]*sz+sz,pos=ed+1;del(0);}
		rep(j,pos,q[i].r) add(j);if(q[i].r>=pos) pos=q[i].r+1;tag=opt.size();
		dwn(j,min(ed,q[i].r),q[i].l) add(j);
		pw=1;inc(ans[q[i].id],res);
		rep(j,1,q[i].k)
		{
			pw=mul(pw,n+1);add(q[i].l-j);add(q[i].r+j);
			inc(ans[q[i].id],mul(res,pw));
		}
		del(tag);
	}
	rep(i,1,Q) printf("%d\n",ans[i]);
}

J

KM 咕

K

考虑对于每个左端点\(l\)找到一个\(r\)使得\([l,r]\)符合条件,则\([l,r+1],\dots [l,n]\)这些区间均符合条件

容易发现当\(l\)右移时,\(r\)也一定右移,不可能左移;因此可以使用滑动窗口

对于区间内的最大值与最小值,可以用单调队列维护

#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 100100
#define MOD 998244353
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pls(a,b) (a+b)%MOD
#define mns(a,b) (a-(b)+MOD)%MOD
#define mul(a,b) (1LL*(a)*(b))%MOD
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline int read()
{
    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 n,m,k,mn[MAXN],mx[MAXN],g[MAXN],h1,t1,h2,t2;
ll ans;
int main()
{
	n=read(),m=read();rep(i,1,n) g[i]=read();
	rep(t,1,m)
	{
		k=read();h1=h2=1,t1=t2=0;ans=0;int l=1;
		rep(i,1,n)
		{
			while(h1<=t1&&g[mx[t1]]<=g[i]) t1--;mx[++t1]=i;
			while(h2<=t2&&g[mn[t2]]>=g[i]) t2--;mn[++t2]=i;
			while(h1<=t1&&h2<=t2&&g[mx[h1]]-g[mn[h2]]>k)
			{
				ans+=n-i+1,l++;
				if(mx[h1]<l) h1++;
				if(mn[h2]<l) h2++;
			}
		}
		printf("%lld\n",ans);
	}
}

标签:ch,21,int,第五场,rep,long,牛客,MOD,define
来源: https://www.cnblogs.com/yyc-jack-0920/p/15089309.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有