R7好诗AK赛(NOIP模拟赛)/省选专练【2018雅礼集训】划分Divide



100+70+30我好菜啊

T1模板题

mannacher可过

卡后缀数组/回文自动机/二分hash

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=2e6+1000;
int RL[N*2]={};
char P[N*2]={};
char s[N*2]={};
void Manachar(char *s,int n){
	int MaxRight=0,pos=0;
    memset(RL,0,sizeof(RL));
	for(int i=0;i<n;i++){
		if(MaxRight>i)
			RL[i]=min(RL[2*pos-i],MaxRight-i);
		else 
			RL[i]=1;
   		while(s[i+RL[i]]==s[i-RL[i]])RL[i]++;
		if(i+RL[i]>MaxRight){
    		MaxRight=i+RL[i];
        	pos=i;
    	}
	}
}
void Change(char *s,int len){
	len=strlen(s);
	P[0]='$';
	for(int i=1;i<=len*2+1;i+=2) P[i]='#';
	for(int i=0;i<len;i++) P[i*2+2]=s[i];
}
int n;
int main(){
	freopen("string.in","r",stdin);
	freopen("string.out","w",stdout);
	scanf("%d%s",&n,s);
	Change(s, n);
//	cout<<strlen(P);
	Manachar(P,n*2+1);
	int ans=-1;
	for(int i=1;i<=n*2+1;i++)
		ans=max(ans,RL[i]);
	cout<<ans-1;
	return 0;
}

T2我就不会了

循环空转了70分

实际就是一个枚举子集

暴力代码:

#include<bits/stdc++.h>
using namespace std;
const int N=3e5+100;
inline void read(int &x){
	x=0;
	char ch=getchar();
	int f=1;
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		x=x*10+ch-'0';
		ch=getchar();
	}
	x*=f;
}
int n;
int maxn=1;
int A[N]={};
int ans[N]={};
int main(){
	freopen("flower.in","r",stdin);
//	freopen("flower.out","w",stdout);
	read(n);
	for(int i=1;i<=n;i++)maxn*=2;
	maxn--;
	for(int i=0;i<=maxn;i++){
		read(A[i]);
	}
	for(int i=0;i<=maxn;i++){
		for(int j=i+1;j<=maxn;j++){
			ans[(i|j)]=max(ans[(i|j)],A[i]+A[j]);
		}
	}
	for(int i=1;i<=maxn;i++){
		ans[i]=max(ans[i],ans[i-1]);
	}
	for(int i=1;i<=maxn;i++){
		cout<<ans[i]<<'\n';
	}
	return 0;
}

正解:

#include<bits/stdc++.h>
using namespace std;
typedef int INT;
#define int long long
const int N=3e5+100;
inline void read(int &x){
	x=0;
	char ch=getchar();
	int f=1;
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		x=x*10+ch-'0';
		ch=getchar();
	}
	x*=f;
}
int A[N]={};
int B[N]={};
int C[N]={};
int F[N]={};
inline int lowbit(int x){
	return x&(-x);
}
void Calc(int x,int y){
	if(x==y)return;
	if(A[y]>=B[x]){
		C[x]=B[x];
		B[x]=A[y];
	}
	else{
		if(A[y]>C[x])C[x]=A[y];
	}
}
int n;
int maxn;
INT main(){
	freopen("flower.in","r",stdin);
	freopen("flower.out","w",stdout);
	read(n);
	maxn=1;
	for(int i=1;i<=n;i++){
		maxn=maxn*2;
	}
	maxn--;
	for(int i=0;i<=maxn;i++)read(A[i]),B[i]=A[i];
	for(int i=1;i<=maxn;i++){
		int Q=lowbit(i);
		for(int st=i^Q;st>=0;st=(st-1)&(i^Q)){
			Calc(i,st);
			Calc(i,st^Q);
			if(st==0)break;
		}
		F[i]=B[i]+C[i];
		F[i]=max(F[i],F[i-1]);
		cout<<F[i]<<'\n';
//		cout<<B[i]<<" "<<C[i]<<'\n';
	}
	return 0;
}

T3又是神仙题。

难道雅礼80省队考生

首先第二个暴力等于不叫暴力、

他根本没有提示你什么

只是告诉你要排序

试想:如果存在一个数组其中元素满足:对于一个i其前面所有值要么加起来大于m要么小于m

辣么可以DP

设F(i,j)表示前i个数有j个A队

F(i,j)=max(F(i-1,j)+C[i]*j,F(i-1,j-1)+C[i]*(i-j))

C:满足>m为1否则为0

然后计数是一个Dag图

Dp可过

怎样构造这个数组?

取队首和队尾相加若大于m把队首压入新的数组

小于m把队尾压入新的数组

翻转该数组。

30分暴力

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
const int N=2101;
const int mod=1e9+7;
inline void read(int &x){
	x=0;
	char ch=getchar();
	int f=1;
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		x=x*10+ch-'0';
		ch=getchar();
	}
	x*=f;
}
int W[N]={};
int G[N][N]={};
int vis[N]={};
int n,m;
int ans1=0;
int ans2=0;
void check(){
	int now=0;
	for(int i=1;i<=n;i++){
		for(int j=i+1;j<=n;j++){
			if((vis[i]!=vis[j])&&G[i][j]){
				now++;	
			}
		}
	}
	if(ans1<now){
		ans1=now;
		ans2=1;
	}
	else{
		if(ans1==now)ans2++,ans2=ans2%mod;
	}
//	return 1;
}
void dfs(int now){
	if(now==n+1){
		check();
		return;
	}
	vis[now]=1;
	dfs(now+1);
	vis[now]=0;
	dfs(now+1);
}
//int matching[N]={};
//void match(int x){
//	for(int i=1;i<=n;i++){
//		if(G[x][i]){
//			
//		}
//	}
//}
//void Hungary(){
//	
//}
int main(){
//	freopen("3651.txt","r",stdin);
//	freopen("curtain.out","w",stdout);
	read(n);
	read(m);
	for(int i=1;i<=n;i++){
		read(W[i]);
	}
	for(int i=1;i<=n;i++){
		for(int j=i+1;j<=n;j++){
			if(W[i]+W[j]>=m){
				G[i][j]=G[j][i]=1;
			}
		}
	}
//	Hungary();
	dfs(1);
	cout<<ans1<<" "<<ans2;
	return 0;
}

标程

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
typedef int INT;
#define int long long 
inline void read(int &x){
	x=0;
	char ch=getchar();
	int f=1;
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		x=x*10+ch-'0';
		ch=getchar();
	}
	x*=f;
}
int f2[1000+20]={};
const int mod=1e9+9;
void Pre(){
	f2[0]=1;
	for(int i=1;i<=1000;i++){
		f2[i]=f2[i-1]*2%mod;
	}
}
const int N=15;
int n,m,k;
int maxn;
int dp[N][1<<N]={};
int f[1<<N]={};
int g[1<<N]={};
int vis[1<<N]={};
int fa[N]={};
inline int lowbit(int x){
	return x&(-x);
}
int getfa(int x){
	if(fa[x]==x)return fa[x];
	else return fa[x]=getfa(fa[x]);
}
void Union(int x,int y){
	int dx=getfa(x);
	int dy=getfa(y);
	fa[dx]=dy;	
}
INT main(){
//	freopen("sarsae.in","r",stdin);
	Pre();
	read(n);
	read(m);
	read(k);
	maxn=(1<<n)-1;
	for(int i=1;i<=m;i++){
		int u,v;
		read(u);
		read(v);
		u--;
		v--;
		for(int j=0;j<=maxn;j++){
			if((j&(1<<u))&&(j&(1<<v))){
//				cout<<"working";
				f[j]++;
			}
		}
		Union(u,v);
	}	
	for(int st=1;st<=maxn;st++){
		int minP=lowbit(st);
		int To=-1;
		int Fail=0;
		for(int j=0;j<n;j++){
			if((1<<j)&st){
				if(To==-1){
					To=getfa(j);		
				}
				else{
					if(To!=getfa(j)){
						Fail=1;
						break;
					}
				}
			}
		}
		if(Fail)continue;
		else vis[st]=1;
		f[st]=f2[f[st]];
		g[st]=f[st];
		for(int j=st;j;j=(j-1)&st){
			if(j==st)continue;
			if(!vis[j])continue;
			if(j&minP){
				f[st]-=f[j]*g[j^st]%mod;
				f[st]%=mod;
			}
		}
	}
//	for(int i=1;i<=maxn;i++){
//		cout<<f[i]<<" ";
//	}
	dp[0][0]=1;
	for(int i=1;i<=k;i++){
		for(int st=1;st<=maxn;st++){
			int p=lowbit(st);
			for(int sub=st;sub;sub=(sub-1)&st){
				if(!vis[sub])continue;
				if(p&sub){
					dp[i][st]+=dp[i-1][st^sub]*f[sub]%mod;
					dp[i][st]%=mod;	
				}	
			}
		}
	} 
	cout<<(dp[k][maxn]+mod)%mod;
}

猜你喜欢

转载自blog.csdn.net/fcb_x/article/details/80990489