【Codeforces #1326】Codeforces Global Round 7题解

传送门

A

随便构造即可

#include<bits/stdc++.h>
using namespace std;
#define cs const
#define re register
#define pb push_back
#define pii pair<int,int>
#define ll long long
#define fi first
#define se second
#define bg begin
cs int RLEN=1<<20|1;
inline char gc(){
    static char ibuf[RLEN],*ib,*ob;
    (ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    return (ib==ob)?EOF:*ib++;
}
inline int read(){
    char ch=gc();
    int res=0;bool f=1;
    while(!isdigit(ch))f^=ch=='-',ch=gc();
    while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    return f?res:-res;
}
inline ll readll(){
    char ch=gc();
    ll res=0;bool f=1;
    while(!isdigit(ch))f^=ch=='-',ch=gc();
    while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    return f?res:-res;
}
inline int readstring(char *s){
	int top=0;char ch=gc();
	while(isspace(ch))ch=gc();
	while(!isspace(ch)&&ch!=EOF)s[++top]=ch,ch=gc();
	return top;
}
template<typename tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
template<typename tp>inline void chemn(tp &a,tp b){a>b?a=b:0;}
cs int mod=1e9+7;
inline int add(int a,int b){return (a+=b)>=mod?(a-mod):a;}
inline int dec(int a,int b){a-=b;return a+(a>>31&mod);}
inline int mul(int a,int b){static ll r;r=1ll*a*b;return (r>=mod)?(r%mod):r;}
inline void Add(int &a,int b){(a+=b)>=mod?(a-=mod):0;}
inline void Dec(int &a,int b){a-=b,a+=a>>31&mod;}
inline void Mul(int &a,int b){static ll r;r=1ll*a*b;a=(r>=mod)?(r%mod):r;}
inline int ksm(int a,int b,int res=1){if(a==0&&b==0)return 0;for(;b;b>>=1,Mul(a,a))(b&1)&&(Mul(res,a),1);return res;}
inline int Inv(int x){return ksm(x,mod-2);}
inline int fix(int x){return (x<0)?x+mod:x;}
int main(){
	#ifdef Stargazer
	freopen("lx.in","r",stdin);
	#endif
	int T=read();
	while(T--){
		int n=read();
		if(n==1)puts("-1");
		else{
			if(n%3==0)
			cout<<4;
			if(n%3==1)
			cout<<5;
			if(n%3==2)
			cout<<4;
			for(int i=1;i<n;i++)cout<<3;
			puts("");
		}
	}
}

B

模拟还原即可

#include<bits/stdc++.h>
using namespace std;
#define cs const
#define re register
#define pb push_back
#define pii pair<int,int>
#define ll long long
#define fi first
#define se second
#define bg begin
cs int RLEN=1<<20|1;
inline char gc(){
    static char ibuf[RLEN],*ib,*ob;
    (ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    return (ib==ob)?EOF:*ib++;
}
inline int read(){
    char ch=gc();
    int res=0;bool f=1;
    while(!isdigit(ch))f^=ch=='-',ch=gc();
    while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    return f?res:-res;
}
inline ll readll(){
    char ch=gc();
    ll res=0;bool f=1;
    while(!isdigit(ch))f^=ch=='-',ch=gc();
    while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    return f?res:-res;
}
inline int readstring(char *s){
	int top=0;char ch=gc();
	while(isspace(ch))ch=gc();
	while(!isspace(ch)&&ch!=EOF)s[++top]=ch,ch=gc();
	return top;
}
template<typename tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
template<typename tp>inline void chemn(tp &a,tp b){a>b?a=b:0;}
cs int mod=1e9+7;
inline int add(int a,int b){return (a+=b)>=mod?(a-mod):a;}
inline int dec(int a,int b){a-=b;return a+(a>>31&mod);}
inline int mul(int a,int b){static ll r;r=1ll*a*b;return (r>=mod)?(r%mod):r;}
inline void Add(int &a,int b){(a+=b)>=mod?(a-=mod):0;}
inline void Dec(int &a,int b){a-=b,a+=a>>31&mod;}
inline void Mul(int &a,int b){static ll r;r=1ll*a*b;a=(r>=mod)?(r%mod):r;}
inline int ksm(int a,int b,int res=1){if(a==0&&b==0)return 0;for(;b;b>>=1,Mul(a,a))(b&1)&&(Mul(res,a),1);return res;}
inline int Inv(int x){return ksm(x,mod-2);}
inline int fix(int x){return (x<0)?x+mod:x;}
int n,a[200005],b[200005];
int main(){
	#ifdef Stargazer
	freopen("lx.in","r",stdin);
	#endif
	n=read();
	for(int i=1;i<=n;i++)a[i]=read();
	for(int mx=0,i=1;i<=n;i++){
		b[i]=mx+a[i];
		chemx(mx,b[i]);
	}
	for(int i=1;i<=n;i++)cout<<b[i]<<" ";
}

C

显然选出最大的 k k k个作为答案
方案就是空隙长度之积

#include<bits/stdc++.h>
using namespace std;
#define cs const
#define re register
#define pb push_back
#define pii pair<int,int>
#define ll long long
#define fi first
#define se second
#define bg begin
cs int RLEN=1<<20|1;
inline char gc(){
    static char ibuf[RLEN],*ib,*ob;
    (ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    return (ib==ob)?EOF:*ib++;
}
inline int read(){
    char ch=gc();
    int res=0;bool f=1;
    while(!isdigit(ch))f^=ch=='-',ch=gc();
    while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    return f?res:-res;
}
inline ll readll(){
    char ch=gc();
    ll res=0;bool f=1;
    while(!isdigit(ch))f^=ch=='-',ch=gc();
    while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    return f?res:-res;
}
inline int readstring(char *s){
	int top=0;char ch=gc();
	while(isspace(ch))ch=gc();
	while(!isspace(ch)&&ch!=EOF)s[++top]=ch,ch=gc();
	return top;
}
template<typename tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
template<typename tp>inline void chemn(tp &a,tp b){a>b?a=b:0;}
cs int mod=998244353;
inline int add(int a,int b){return (a+=b)>=mod?(a-mod):a;}
inline int dec(int a,int b){a-=b;return a+(a>>31&mod);}
inline int mul(int a,int b){static ll r;r=1ll*a*b;return (r>=mod)?(r%mod):r;}
inline void Add(int &a,int b){(a+=b)>=mod?(a-=mod):0;}
inline void Dec(int &a,int b){a-=b,a+=a>>31&mod;}
inline void Mul(int &a,int b){static ll r;r=1ll*a*b;a=(r>=mod)?(r%mod):r;}
inline int ksm(int a,int b,int res=1){if(a==0&&b==0)return 0;for(;b;b>>=1,Mul(a,a))(b&1)&&(Mul(res,a),1);return res;}
inline int Inv(int x){return ksm(x,mod-2);}
inline int fix(int x){return (x<0)?x+mod:x;}
cs int N=200005;
int n,k,a[N];
pii b[N];
int main(){
	n=read(),k=read();
	for(int i=1;i<=n;i++)b[i].fi=read(),b[i].se=i;
	sort(b+1,b+n+1);
	reverse(b+1,b+n+1);
	ll res=0;
	for(int i=1;i<=k;i++)res+=b[i].fi,a[i]=b[i].se;
	sort(a+1,a+k+1);int ret=1;
	for(int i=2;i<=k;i++)Mul(ret,a[i]-a[i-1]);
	cout<<res<<" "<<ret<<'\n';
	return 0;
}

D

脑残写了个没用的双哈希结果被卡了。。。
q n m d qnmd qnmd

考虑先用 m a n a c h e r manacher manacher求出每个位置 p p p为中心的最长回文长度
如果 p ≤ n / 2 p\le n/2 pn/2那么 p p p为中心的最长回文子串前面的一定需要和后面一段后缀匹配
否则 p p p的最长回文子串后面剩下的一定会和一段前缀匹配
对于单双回文串分类判断一下

复杂度 O ( n ) O(n) O(n)

By Backseat-Stargazer, contest: Codeforces Global Round 7, problem: (D2) Prefix-Suffix Palindrome (Hard version), Accepted, #, Copy, hack it!
#include<bits/stdc++.h>
using namespace std;
#define cs const
#define re register
#define pb push_back
#define pii pair<int,int>
#define ll long long
#define fi first
#define se second
#define bg begin
cs int RLEN=1<<20|1;
inline char gc(){
    static char ibuf[RLEN],*ib,*ob;
    (ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    return (ib==ob)?EOF:*ib++;
}
inline int read(){
    char ch=gc();
    int res=0;bool f=1;
    while(!isdigit(ch))f^=ch=='-',ch=gc();
    while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    return f?res:-res;
}
inline ll readll(){
    char ch=gc();
    ll res=0;bool f=1;
    while(!isdigit(ch))f^=ch=='-',ch=gc();
    while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    return f?res:-res;
}
inline int readstring(char *s){
	int top=0;char ch=gc();
	while(isspace(ch))ch=gc();
	while(!isspace(ch)&&ch!=EOF)s[++top]=ch,ch=gc();
	return top;
}
template<typename tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
template<typename tp>inline void chemn(tp &a,tp b){a>b?a=b:0;}
int n,l,mxlen;
cs int N=2000005;
char s[N],t[N];
inline bool check(int p){
	return p<=mxlen;
};
int len[N];
int main(){
	#ifdef Stargazer
	freopen("lx.in","r",stdin);
	#endif
	int T=read();
	while(T--){
	n=readstring(t);
	mxlen=0;
	for(int i=1;i<=n;i++)if(t[i]!=t[n-i+1]){break;}else mxlen=i;
	l=0;
	s[0]='!',s[l=1]='&';
	for(int i=1;i<=n;i++)s[++l]=t[i],s[++l]='&';
	s[l+1]='@';
	for(int i=1,mxpos=0,r=0;i<=l;i++){
//	cout<<s[i];
		if(i<=r)len[i]=min(r-i+1,len[2*mxpos-i]);
		while(s[i+len[i]]==s[i-len[i]])len[i]++;
		if(i+len[i]-1>r)r=i+len[i]-1,mxpos=i;
	}int res=0,p1=0,p2=0;
	for(int i=1;i<=l;i++){
		int le=len[i]-1,p=i/2;
		if(i&1){
			if(p<=n/2){
				int cp=p-(le/2);
				if(check(cp)&&res<cp*2+le){
					res=cp*2+le,p1=p+(le/2),p2=n-cp+1;
				}
			}
			else{
				int cp=p+1+(le/2);
				if(check(n-cp+1)&&res<2*(n-cp+1)+le){
					res=(n-cp+1)*2+le,p1=n-cp+1,p2=p-(le/2)+1;
				}
			}
		}
		else{
			if(p<=n/2){
				int cp=p-(le/2)-1;
				if(check(cp)&&res<cp*2+le){
					res=cp*2+le,p1=p+(le/2),p2=n-cp+1;
				}
			}
			else{
				int cp=p+(le/2)+1;
				if(check(n-cp+1)&&res<2*(n-cp+1)+le){
					res=(n-cp+1)*2+le,p1=n-cp+1,p2=p-(le/2);
				}
			}
		}
	}
	for(int i=1;i<=p1;i++)cout<<t[i];
	for(int i=p2;i<=n;i++)cout<<t[i];
	puts("");
	for(int i=1;i<=l;i++)len[i]=0;
	}
}

E

考虑对于每次操作维护答案没有容易的做法
考虑对于当前答案 x x x
如果答案变成了 x − 1 x-1 x1
那么一定满足对于每个位置 p p p
( p 及 之 后 ≥ x 的 数 的 数 量 ) ≤ p 后 面 炸 弹 的 数 量 (p及之后\geq x的数的数量)\le p后面炸弹的数量 (px)p
f p = ( p 及 之 后 ≥ x 的 数 的 数 量 ) − p 后 面 炸 弹 的 数 量 ≤ 0 f_p=(p及之后\geq x的数的数量)-p后面炸弹的数量\le0 fp=(px)p0
又显然每次操作后答案一定是单调不增的

于是用线段树维护每个位置的 f f f
复杂度 O ( n l o g n ) O(nlogn) O(nlogn)

#include<bits/stdc++.h>
using namespace std;
#define cs const
#define re register
#define pb push_back
#define pii pair<int,int>
#define ll long long
#define fi first
#define se second
#define bg begin
cs int RLEN=1<<20|1;
inline char gc(){
    static char ibuf[RLEN],*ib,*ob;
    (ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    return (ib==ob)?EOF:*ib++;
}
inline int read(){
    char ch=gc();
    int res=0;bool f=1;
    while(!isdigit(ch))f^=ch=='-',ch=gc();
    while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    return f?res:-res;
}
inline ll readll(){
    char ch=gc();
    ll res=0;bool f=1;
    while(!isdigit(ch))f^=ch=='-',ch=gc();
    while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    return f?res:-res;
}
inline int readstring(char *s){
	int top=0;char ch=gc();
	while(isspace(ch))ch=gc();
	while(!isspace(ch)&&ch!=EOF)s[++top]=ch,ch=gc();
	return top;
}
template<typename tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
template<typename tp>inline void chemn(tp &a,tp b){a>b?a=b:0;}
cs int N=300005;
int n,p[N],q[N],pos[N];
namespace Seg{
	cs int N=::N<<2;
	int mx[N],tag[N];
	#define lc (u<<1)
	#define rc ((u<<1)|1)
	#define mid ((l+r)>>1)
	void update(int u,int l,int r,int st,int des,int k){
		if(st<=l&&r<=des)return tag[u]+=k,mx[u]+=k,void();
		if(st<=mid)update(lc,l,mid,st,des,k);
		if(mid<des)update(rc,mid+1,r,st,des,k);
		mx[u]=max(mx[lc],mx[rc])+tag[u];
	}
	#undef lc
	#undef rc
	#undef mid
}
int main(){
	#ifdef Stargazer
	freopen("lx.in","r",stdin);
	#endif
	n=read();
	for(int i=1;i<=n;i++)p[i]=read(),pos[p[i]]=i;
	for(int i=1;i<=n;i++)q[i]=read();
	int ans=n+1;
	for(int i=1;i<=n;i++){
		while(Seg::mx[1]<=0){
			ans--;
			Seg::update(1,1,n,1,pos[ans],1);
		}
		cout<<ans<<" ";
		Seg::update(1,1,n,1,q[i],-1);
	}return 0;
}

F

好像 e a s y easy easy直接 n 2 2 n n2^{2n} n22n都可以过。。。
对于 h a r d hard hard考虑容斥
a n s s t a ans_{sta} anssta表示 s t a sta sta 1 1 1满足 p i , p i + 1 p_i,p_{i+1} pi,pi+1一定相连, 0 0 0为可能相连可能不相连的方案数
如果有 a n s ans ans显然可以轻松知道答案

一个结论是对于一个状态 s s s的方案数
我们只关心里面连续的 1 1 1的段的长度的集合
例如 111011 111011 111011 110111 110111 110111方案数是一样的
而段数的集合实际上是一个类似整数拆分
最多只有不到 400 400 400

考虑先 d p dp dp f s f_s fs表示走了 s s s内的点的方案数
那么一个集合 v 1 , v 2 , . . . . v k v_1,v_2,....v_k v1,v2,....vk的答案就是 ∑ ∏ i , c n t [ m i ] = v i f m i \sum_{}\prod_{i,cnt[m_i]=v_i}f_{m_i} i,cnt[mi]=vifmi
其中满足 ∑ c n t [ m i ] = n 且 m 的 O R 和 为 2 n − 1 , c n t 表 示 其 中 为 1 的 个 数 \sum cnt[m_i]=n且m的OR和为2^n-1,cnt表示其中为1的个数 cnt[mi]=nmOR2n1,cnt1
由于有 ∑ c n t = n \sum cnt=n cnt=n的限制不会出现某个点出现在多个 m m m

这个直接一边枚举整数拆分一边乘就可以过了

#include<bits/stdc++.h>
using namespace std;
#define cs const
#define re register
#define pb push_back
#define pii pair<int,int>
#define ll long long
#define fi first
#define se second
#define bg begin
cs int RLEN=1<<20|1;
inline char gc(){
    static char ibuf[RLEN],*ib,*ob;
    (ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    return (ib==ob)?EOF:*ib++;
}
inline int read(){
    char ch=gc();
    int res=0;bool f=1;
    while(!isdigit(ch))f^=ch=='-',ch=gc();
    while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    return f?res:-res;
}
inline ll readll(){
    char ch=gc();
    ll res=0;bool f=1;
    while(!isdigit(ch))f^=ch=='-',ch=gc();
    while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    return f?res:-res;
}
inline int readstring(char *s){
	int top=0;char ch=gc();
	while(isspace(ch))ch=gc();
	while(!isspace(ch)&&ch!=EOF)s[++top]=ch,ch=gc();
	return top;
}
template<typename tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
template<typename tp>inline void chemn(tp &a,tp b){a>b?a=b:0;}
cs int N=19,M=(1<<N)+3;
int n,m,cnt[M];
ll val[M],ans[M],f[N][M],dp[M][N],s[M];
vector<int> e[N];
char str[N];
vector<int> now;
map<vector<int>,vector<int>> sta;
inline void calc(){
	ll res=0;
	for(int i=0;i<m;i++)
	if(cnt[i^(m-1)]&1)res-=val[i];
	else res+=val[i];
	for(int &s:sta[now])
	ans[s]+=res;
}
void dfs(int s,int mx){
	if(s>n)return;
	if(s==n)return calc();
	vector<ll> pre(m);
	for(int i=0;i<m;i++)pre[i]=val[i];
	for(int i=mx;i+s<=n;i++){
		if(s+i!=n&&s+i+i>n)continue;
		now.pb(i);
		for(int j=0;j<m;j++)
		val[j]*=f[i][j];
		dfs(s+i,i);
		for(int j=0;j<m;j++)
		val[j]=pre[j];
		now.pop_back();
	}
}
inline void fmt(ll *f,int lim){
	for(int mid=1;mid<lim;mid<<=1)
	for(int i=0;i<lim;i+=mid<<1)
	for(int j=0;j<mid;j++)
	f[i+j+mid]+=f[i+j];
}
int main(){
	#ifdef Stargazer
	freopen("lx.in","r",stdin);
	#endif
	n=read(),m=1<<n;
	for(int i=1;i<m;i++)cnt[i]=cnt[i>>1]+(i&1);
	for(int i=0;i<n;i++){
		readstring(str);
		for(int j=1;j<=n;j++)if(str[j]=='1'){
			e[i].pb(j-1);
		}
	}
	for(int i=0;i<n;i++)dp[1<<i][i]=1;
	for(int i=1;i<m;i++){
		ll res=0;
		for(int j=0;j<n;j++)if(i&(1<<j)){
			ll now=dp[i][j];
			for(int &k:e[j])if(!(i&(1<<k))){
				dp[i+(1<<k)][k]+=now;
			}
			res+=dp[i][j];
		}
		f[cnt[i]][i]=res;
	}
	for(int i=1;i<=n;i++)fmt(f[i],m);
	for(int i=0;i<m/2;i++){
		vector<int> pt;int p=0;
		while(p<n){
			int len=1;
			while(i&(1<<p)){
				len++,p++;
			}
			pt.pb(len),p++;
		}
		sort(pt.bg(),pt.end());
		sta[pt].pb(i);
	}
	for(int i=0;i<m;i++)val[i]=1;
	dfs(0,1);
	for(int mid=1;mid<m;mid<<=1)
	for(int i=0;i<m/2;i+=mid<<1)
	for(int j=0;j<mid;j++)
	ans[i+j]-=ans[i+j+mid];
	for(int i=0;i<m/2;i++)cout<<ans[i]<<" ";
	return 0;
}

G

不会告辞
咕咕咕

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值