
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;
}