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

R7好诗AK赛(NOIP模拟赛)/省选专练【2018雅礼集训】划分Divide_第1张图片

R7好诗AK赛(NOIP模拟赛)/省选专练【2018雅礼集训】划分Divide_第2张图片

R7好诗AK赛(NOIP模拟赛)/省选专练【2018雅礼集训】划分Divide_第3张图片

100+70+30我好菜啊

T1模板题

mannacher可过

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

#include
#include
#include
#include
#include
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;ii)
			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

T2我就不会了

循环空转了70分

实际就是一个枚举子集

暴力代码:

#include
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<

正解:

#include
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<

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
#include
#include
#include
#include
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=m){
				G[i][j]=G[j][i]=1;
			}
		}
	}
//	Hungary();
	dfs(1);
	cout<

标程

#include
#include
#include
#include
#include
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<

你可能感兴趣的:(OI套题,动态规划,智商题,mannacher)