XII Open Cup named after E.V. Pankratiev. GP of Eastern Europe (AMPPZ-2012)
A. Automat
m超过1600是没用的。
从后往前考虑,设f[i][j][k]表示考虑[i,n]这些物品,一共花费j元钱,买了k个物品的最大收益。
时间复杂度O(n5)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | #include<cstdio> const int N=45,M=1605; int n,m,lim,A,B,i,j,k,x,y,z,o,a[N],b[N],f[2][M][N],ans; inline void up( int &a, int b){a<b?(a=b):0;} inline int min( int a, int b){ return a<b?a:b;} int main(){ scanf ( "%d%d" ,&n,&m); m=min(m,M-5); lim=40; for (i=1;i<=n;i++) scanf ( "%d" ,&a[i]); for (i=1;i<=n;i++) scanf ( "%d" ,&b[i]); for (o=0;o<2;o++) for (i=0;i<=m;i++) for (j=0;j<=lim;j++)f[o][i][j]=-1; o=0; f[0][0][0]=0; for (i=n;i;i--,o^=1){ A=a[i],B=b[i]; for (j=0;j<=m;j++) for (k=0;k<=lim;k++)f[o^1][j][k]=-1; for (j=0;j<=m;j++) for (x=0;x<=B&&j+x*A<=m;x++) for (k=0;k<=lim;k++) if (~f[o][j][k]) up(f[o^1][j+x*A][min(k+x,lim)],f[o][j][k]+min(k+x,B)*A); } for (i=0;i<=m;i++) for (j=0;j<=lim;j++)up(ans,f[o][i][j]); printf ( "%d" ,ans); } |
B. Touristic Bureau
将所有景点按照有趣度从小到大排序,设f[i]表示走到i的最大获利,则f[i]=max(f[j]+manhattan(i,j))+c[i](j<i)。
枚举曼哈顿距离里x和y的符号,分别维护最大值即可。
时间复杂度O(nm)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | #include<cstdio> #include<algorithm> #include<vector> using namespace std; typedef pair< int , int >P; typedef long long ll; const int N=1010,M=N*N; const ll inf=1LL<<60; int n,m,i,j,x,c[N][N];vector<P>v[M]; ll g[4],f[N][N],ans; inline void up(ll&a,ll b){a<b?(a=b):0;} inline void cal( int x, int y){ ll t=0; up(t,x+y+g[0]); //-x-y up(t,x-y+g[1]); //-x+y up(t,-x+y+g[2]); //x-y up(t,-x-y+g[3]); //x+y up(ans,f[x][y]=t+c[x][y]); } inline void ins( int x, int y){ ll t=f[x][y]; up(g[0],t-x-y); up(g[1],t-x+y); up(g[2],t+x-y); up(g[3],t+x+y); } int main(){ scanf ( "%d%d" ,&n,&m); for (i=1;i<=n;i++) for (j=1;j<=m;j++){ scanf ( "%d" ,&x); if (x)v[x].push_back(P(i,j)); } for (i=1;i<=n;i++) for (j=1;j<=m;j++) scanf ( "%d" ,&c[i][j]); g[0]=g[1]=g[2]=g[3]=-inf; for (i=1;i<M;i++){ for (j=0;j<v[i].size();j++)cal(v[i][j].first,v[i][j].second); for (j=0;j<v[i].size();j++)ins(v[i][j].first,v[i][j].second); } printf ( "%lld" ,ans); } |
C. Sequence
下标模k相同的位置最后要一样,故直接将序列长度压缩成k然后DP即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | #include<cstdio> const int N=1000010; int n,k,i,j,x,cnt[N][2],f[N][2]; inline void up( int &a, int b){a>b?(a=b):0;} int main(){ scanf ( "%d%d" ,&n,&k); for (i=1;i<=n;i++){ scanf ( "%d" ,&x); cnt[i%k][x&1]++; } for (i=0;i<=k;i++)f[i][0]=f[i][1]=N; f[0][0]=0; for (i=0;i<k;i++) for (j=0;j<2;j++){ up(f[i+1][j],f[i][j]+cnt[i][1]); up(f[i+1][j^1],f[i][j]+cnt[i][0]); } printf ( "%d" ,f[k][0]); } |
D. DNA
字符集=1最优。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=100010; int n,i,b[N]; char a[N],ans; int main(){ scanf ( "%d%s" ,&n,a+1); for (i=1;i<=n;i++)b[a[i]]++; ans= 'A' ; if (b[ 'C' ]<b[ans])ans= 'C' ; if (b[ 'T' ]<b[ans])ans= 'T' ; if (b[ 'G' ]<b[ans])ans= 'G' ; printf ( "%d\n" ,b[ans]); for (i=1;i<=n;i++) putchar (ans); } |
E. Evaluation
对表达式递归建树,设f[i][j]表示i子树内运算结果为j的方案数。
对于求幂直接计算。
对于加法可以FFT。
对于乘法可以求出原根后取指标然后转化为加法FFT。
时间复杂度O(nPlogP)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> using namespace std; typedef vector< int >V; const int N=70000,MO=30011; int P,n,i,j,len,po[MO][10],pos[N],A[N],B[N],C[N]; int ind[N],gen[N],G; char a[310]; namespace FFT{ typedef long double ld; const ld pi= acos (-1.0); struct comp{ ld r,i; comp(ld _r=0,ld _i=0){r=_r,i=_i;} comp operator+( const comp&x){ return comp(r+x.r,i+x.i);} comp operator-( const comp&x){ return comp(r-x.r,i-x.i);} comp operator*( const comp&x){ return comp(r*x.r-i*x.i,r*x.i+i*x.r);} comp conj(){ return comp(r,-i);} }A[N],B[N]; inline void FFT(comp a[], int n, int t){ for ( int i=1;i<n;i++) if (i<pos[i])swap(a[i],a[pos[i]]); for ( int d=0;(1<<d)<n;d++){ int m=1<<d,m2=m<<1; ld o=pi*2/m2*t;comp _w( cos (o), sin (o)); for ( int i=0;i<n;i+=m2){ comp w(1,0); for ( int j=0;j<m;j++){ comp&A=a[i+j+m],&B=a[i+j],t=w*A; A=B-t; B=B+t; w=w*_w; } } } if (t==-1) for ( int i=0;i<n;i++)a[i].r/=n; } inline void mul( int *a, int *b, int *c){ int i,j; for (i=0;i<len;i++)A[i]=comp(a[i],b[i]); FFT(A,len,1); for (i=0;i<len;i++){ j=(len-i)&(len-1); B[i]=(A[i]*A[i]-(A[j]*A[j]).conj())*comp(0,-0.25); } FFT(B,len,-1); for (i=0;i<len;i++)c[i]=(( long long )(B[i].r+0.5))%MO; } } V dfs( int l, int r){ if (l==r){ V v; v.resize(P); for ( int i=0;i<P;i++)v[i]=0; if (a[l]>= '0' &&a[l]<= '9' )v[(a[l]- '0' )%P]=1; if (a[l]>= 'a' &&a[l]<= 'z' ) for ( int i=0;i<P;i++)v[i]=1; return v; } l++,r--; int al=-1,ar,bl,br,op; if (a[l]!= '(' ){ al=ar=l; bl=l+2; br=r; op=a[l+1]; } else for ( int i=l,t=0;i<=r;i++){ if (a[i]== '(' )t++; if (a[i]== ')' ){ t--; if (!t){ al=l; ar=i; bl=i+2; br=r; op=a[i+1]; break ; } } } V vl=dfs(al,ar),vr,v; v.resize(P); for ( int i=0;i<P;i++)v[i]=0; if (op!= '^' )vr=dfs(bl,br); if (op== '^' ){ int k=a[bl]- '0' ; //printf("[%d,%d]^%d\n",al,ar,k); for ( int i=0;i<P;i++)(v[po[i][k]]+=vl[i])%=MO; } if (op== '+' ){ //printf("[%d,%d]+[%d,%d]\n",al,ar,bl,br); for ( int i=0;i<len;i++)A[i]=B[i]=C[i]=0; for ( int i=0;i<P;i++)A[i]=vl[i],B[i]=vr[i]; FFT::mul(A,B,C); for ( int i=0;i<len;i++)(v[i%P]+=C[i])%=MO; } if (op== '*' ){ //printf("[%d,%d]*[%d,%d]\n",al,ar,bl,br); for ( int i=0;i<P;i++)v[0]=(1LL*vl[0]*vr[i]+v[0])%MO; for ( int i=1;i<P;i++)v[0]=(1LL*vl[i]*vr[0]+v[0])%MO; for ( int i=0;i<len;i++)A[i]=B[i]=C[i]=0; for ( int i=1;i<P;i++)A[ind[i]]=vl[i],B[ind[i]]=vr[i]; FFT::mul(A,B,C); for ( int i=0;i<len;i++)(v[gen[i%(P-1)]]+=C[i])%=MO; } //for(int i=0;i<P;i++)printf("->%d %d\n",i,v[i]); return v; } inline int powmod( int a, int b, int P){ int t=1; for (;b;b>>=1,a=1LL*a*a%P) if (b&1)t=1LL*t*a%P; return t; } int getG( int n){ if (n==2) return 1; int i,j,t=0; static int q[N]; for (i=2;1LL*i*i<=n-1;i++) if ((n-1)%i==0)q[t++]=i,q[t++]=(n-1)/i; for (i=2;;i++){ for (j=0;j<t;j++) if (powmod(i,q[j],n)==1) break ; if (j==t) return i; } } int main(){ scanf ( "%d%s" ,&P,a+1); n= strlen (a+1); if (n==1){ if (a[1]== '0' ) return puts ( "1" ),0; if (a[1]>= 'a' &&a[1]<= 'z' ) return puts ( "1" ),0; return puts ( "0" ),0; } for (len=1;len<P*2;len<<=1); j=__builtin_ctz(len)-1; for (i=0;i<len;i++)pos[i]=pos[i>>1]>>1|((i&1)<<j); for (i=0;i<MO;i++) for (po[i][0]=j=1;j<10;j++)po[i][j]=1LL*po[i][j-1]*i%P; G=getG(P); for (i=0,j=1;i<P-1;i++){ gen[i]=j; ind[j]=i; j=1LL*j*G%P; } V ret=dfs(1,n); printf ( "%d" ,ret[0]); } |
F. Formula-1
设s[k]为第k辆车最多能进行的超车次数,A[k]表示它前面那些车给s[k]的贡献,B[k]为后面的,则A[k]=∑k−1i=1(a[i]+1)。
设b[i]为第i辆车为了到k+1这个位置最少需要的超车次数,则b[k+1]=0,b[i+1]=b[i]+[a[i]≤b[i]],且B[k]=∑ni=k+1max(a[i]−b[i],0)。
若对于每个k都有s[k]≥a[k],则可行。
找出最大的m满足A[m]≤a[m],则除了m之外所有车都可行,暴力检查m即可。
时间复杂度O(n)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | #include<cstdio> const int N=1000010,BUF=30000000; int Case,n,i,k,a[N],b[N]; long long s[N]; char Buf[BUF],*buf=Buf; inline void read( int &a){ for (a=0;*buf<48;buf++); while (*buf>47)a=a*10+*buf++-48;} int main(){ fread (Buf,1,BUF,stdin);read(Case); while (Case--){ read(n); for (i=1;i<=n;i++)read(a[i]); for (s[1]=0,i=2;i<=n;i++)s[i]=s[i-1]+a[i-1]+1; for (i=1;i<=n;i++) if (s[i]<=a[i])k=i; for (b[i=k+1]=0;i<n;i++)b[i+1]=b[i]+(a[i]<=b[i]); for (i=k+1;i<=n;i++) if (a[i]>b[i])s[k]+=a[i]-b[i]; puts (s[k]>=a[k]? "TAK" : "NIE" ); } return 0; } |
G. General
如果凸包大小≤2,那么特判即可。
否则凸包大小至少为3,对于每个询问,首先在凸包上按极角二分出一条边,看看是否在凸包内或者边上。
如果不在,那么往左往右二分出两条切线的位置,然后用叉积前缀和回答询问即可。
时间复杂度O((n+m)logn)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | #include<cstdio> #include<algorithm> using namespace std; typedef long long ll; const int N=100010; int n,m,ce,i,j,x,y,z,ca,cb,cnt;ll f[N<<1]; struct P{ int x,y; P(){} P( int _x, int _y){x=_x,y=_y;} P operator-( const P&b){ return P(x-b.x,y-b.y);} void operator-=( const P&b){* this =* this -b;} bool operator==( const P&b){ return x==b.x&&y==b.y;} bool operator!=( const P&b){ return x!=b.x||y!=b.y;} }a[N],b,c[N<<1],O; inline bool cmp( const P&a, const P&b){ return a.x==b.x?a.y<b.y:a.x<b.x;} inline ll cross( const P&a, const P&b){ return 1LL*a.x*b.y-1LL*a.y*b.x;} inline void read( int &a){ char c; bool f=0;a=0; while (!((((c= getchar ())>= '0' )&&(c<= '9' ))||(c== '-' ))); if (c!= '-' )a=c- '0' ; else f=1; while (((c= getchar ())>= '0' )&&(c<= '9' ))(a*=10)+=c- '0' ; if (f)a=-a; } int convexhull(P*p, int n,P*q){ int i,k,m; for (i=m=0;i<n;q[m++]=p[i++]) while (m>1&&cross(q[m-1]-q[m-2],p[i]-q[m-2])<=0)m--; k=m; for (i=n-2;i>=0;q[m++]=p[i--]) while (m>k&&cross(q[m-1]-q[m-2],p[i]-q[m-2])<=0)m--; return --m; } inline bool point_on_segment(P p,P a,P b){ return !cross(b-a,p-a)&&1LL*(p.x-a.x)*(p.x-b.x)+1LL*(p.y-a.y)*(p.y-b.y)<=0; } inline int askl( int l, int r,P p){ int t=l++,mid; while (l<=r){ mid=(l+r)>>1; if (cross(c[mid]-p,c[(mid-1+n)%n]-c[mid])<=0)l=(t=mid)+1; else r=mid-1; } return t; } inline int askr( int l, int r,P p){ int t=r--,mid; while (l<=r){ mid=(l+r)>>1; if (cross(c[mid]-p,c[(mid+1)%n]-c[mid])>=0)r=(t=mid)-1; else l=mid+1; } return t; } inline ll solve(P p){ if (n<2) return 0; if (n==2) return abs (f[0]+cross(c[1],p)+cross(p,c[0])); if (point_on_segment(p,c[0],c[n-1])) return f[n-1]; int o=0; if (p.x>0){ int l=1,r=n-1,mid; while (l<=r) if (cross(c[mid=(l+r)>>1],p)>=0)l=(o=mid)+1; else r=mid-1; } else if (p.y>0)o=n-1; if (p.x>=0&&cross(p-c[o],c[o+1]-p)<0) return f[n-1]; if (p.x>=0&&point_on_segment(p,c[o],c[o+1])) return f[n-1]; int l,r; if (p.x>0)l=askl(0,o,p),r=askr(o,n,p); else l=askl(m,n,p),r=askr(0,m,p); if (l>r)r+=n; return f[n-1]+cross(c[l],p)+cross(p,c[r])-f[r-1]+f[l-1]; } int main(){ read(ca),read(cb); for (i=1;i<=ca;i++)read(a[i].x),read(a[i].y); cnt=ca; sort(a+1,a+ca+1,cmp); for (ca=0,i=1;i<=cnt;i++) if (i==1||a[i]!=a[i-1])a[++ca]=a[i]; n=convexhull(a+1,ca,c); for (O=c[0],i=0;i<n;i++)c[i]-=O; for (i=0;i<n;i++) if (c[i].x>=c[m].x)m=i; for (i=0;i<n;i++)c[i+n]=c[i]; for (i=0;i<n+n;i++){ f[i]=cross(c[i],c[i+1]); if (i)f[i]+=f[i-1]; } while (cb--){ read(b.x),read(b.y); ll tmp=solve(b-O); printf ( "%lld.%lld\n" ,tmp/2,tmp%2*5); } return 0; } |
H. Hydra
设f[x]为击杀x的最小代价,则f[x]=min(k[x],s[x]+∑(f[x的后继])),用SPFA来循环更新即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | #include<cstdio> typedef long long ll; const int N=200010,M=1000010,P=1048575,BUF=20000000; int n,i,j,x,g[N],v[M],nxt[M],ed,in[N],h,t,q[P+1];ll f[N],f2[N]; char Buf[BUF],*buf=Buf; inline void read( int &a){ for (a=0;*buf<48;buf++); while (*buf>47)a=a*10+*buf++-48;} inline void read(ll&a){ for (a=0;*buf<48;buf++); while (*buf>47)a=a*10+*buf++-48;} inline void add( int x, int y){v[++ed]=y;nxt[ed]=g[x];g[x]=ed;} int main(){ for ( fread (Buf,1,BUF,stdin),read(n),i=1;i<=n;i++) for (read(f2[i]),read(f[i]),read(j);j--;add(x,i))read(x); for (i=1;i<=n;i++) for (j=g[i];j;j=nxt[j])f2[v[j]]+=f[i]; for (i=h=1;i<=n;i++)in[q[++t]=i]=1; while (h!=((t+1)&P)){ x=q[h++],h&=P; if (f[x]>f2[x]){ for (i=g[x];i;i=nxt[i]){ f2[j=v[i]]-=f[x]-f2[x]; if (!in[j]){ in[j]=1; q[h=(h-1+P)&P]=j; } } f[x]=f2[x]; } in[x]=0; } return printf ( "%lld" ,f[1]),0; } |
I. Inversions
线段树优化BFS。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | #include<cstdio> #include<algorithm> using namespace std; const int N=1000010,M=2222222; int n,i,j,a[N],vmi[M],vma[M],mx,tot,e[N][2]; int q[N],h,t; bool vis[N]; inline void up( int x){ vmi[x]=min(vmi[x<<1],vmi[x<<1|1]); vma[x]=max(vma[x<<1],vma[x<<1|1]); } void build( int x, int a, int b){ if (a==b){ vmi[x]=vma[x]=::a[a]; return ; } int mid=(a+b)>>1; build(x<<1,a,mid),build(x<<1|1,mid+1,b); up(x); } void clear( int x, int a, int b, int c){ if (a==b){ vis[q[++t]=a]=1; vmi[x]=N,vma[x]=0; return ; } int mid=(a+b)>>1; if (c<=mid)clear(x<<1,a,mid,c); else clear(x<<1|1,mid+1,b,c); up(x); } void bigger( int x, int a, int b, int c, int d, int p){ if (vma[x]<p) return ; if (a==b){ vis[q[++t]=a]=1; vmi[x]=N,vma[x]=0; return ; } int mid=(a+b)>>1; if (c<=mid)bigger(x<<1,a,mid,c,d,p); if (d>mid)bigger(x<<1|1,mid+1,b,c,d,p); up(x); } void smaller( int x, int a, int b, int c, int d, int p){ if (vmi[x]>p) return ; if (a==b){ vis[q[++t]=a]=1; vmi[x]=N,vma[x]=0; return ; } int mid=(a+b)>>1; if (c<=mid)smaller(x<<1,a,mid,c,d,p); if (d>mid)smaller(x<<1|1,mid+1,b,c,d,p); up(x); } inline void bfs( int S){ mx=S; h=1,t=0; clear(1,1,n,S); while (h<=t){ int x=q[h++]; if (x>mx)mx=x; if (x>1)bigger(1,1,n,1,x-1,a[x]); if (x<n)smaller(1,1,n,x+1,n,a[x]); } } int main(){ scanf ( "%d" ,&n); for (i=1;i<=n;i++) scanf ( "%d" ,&a[i]); build(1,1,n); for (i=1;i<=n;i++) if (!vis[i]){ bfs(i); tot++; e[tot][0]=i; e[tot][1]=mx; } printf ( "%d\n" ,tot); for (i=1;i<=tot;i++){ printf ( "%d" ,e[i][1]-e[i][0]+1); for (j=e[i][0];j<=e[i][1];j++) printf ( " %d" ,j); puts ( "" ); } } |
J. Procrastination
按时间从后往前贪心安排任务。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #include<cstdio> #include<algorithm> using namespace std; typedef long long ll; const int N=1000010; int n,i;ll cur; struct P{ int d,t;}a[N]; inline bool cmp( const P&a, const P&b){ return a.t>b.t;} int main(){ scanf ( "%d" ,&n); for (i=1;i<=n;i++) scanf ( "%d%d" ,&a[i].d,&a[i].t); sort(a+1,a+n+1,cmp); cur=1LL<<60; for (i=1;i<=n;i++){ if (cur>a[i].t)cur=a[i].t-a[i].d+1; else cur-=a[i].d; } printf ( "%lld" ,cur-1); } |
K. Rabbits
若n=3,那么贪心取最大的k个即可。
否则打枪顺序无关,要么第一枪打1,要么第一枪打2,要么打3..n。
第一枪打1和2时,模拟出变化后的情况,并将次数减1,将环当成序列考虑,那么不能在相邻两个位置打枪,若i和i−2都打枪,那么可以同时打到i−1,DP即可。
第一枪打3..n时,可以直接将环当成链DP。
时间复杂度O(nk)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | #include<cstdio> #include<algorithm> const int N=4010,M=2010; int n,m,K,i,j,a[N*2],b[N],f[2][M][2][2],ans; inline void up( int &a, int b){a<b?(a=b):0;} inline int dp( int flag){ if (!K) return 0; if (flag){ b[2]+=b[1],b[m-1]+=b[m]; b[1]=b[m]=0; } int i,j,x,y,o=0,ret=0; for (j=0;j<=K;j++) for (x=0;x<2;x++) for (y=0;y<2;y++)f[o][j][x][y]=-1; f[o][0][0][0]=0; for (i=0;i<m;i++,o^=1){ for (j=0;j<=K;j++) for (x=0;x<2;x++) for (y=0;y<2;y++)f[o^1][j][x][y]=-1; for (j=0;j<=K;j++) for (x=0;x<2;x++) for (y=0;y<2;y++) if (~f[o][j][x][y]){ up(f[o^1][j][y][0],f[o][j][x][y]); if (!y&&j<K){ if (x)up(f[o^1][j+1][y][1],f[o][j][x][y]+b[i]+b[i+1]); else up(f[o^1][j+1][y][1],f[o][j][x][y]+b[i+1]); } } } for (j=0;j<=K;j++) for (x=0;x<2;x++) for (y=0;y<2;y++)up(ret,f[o][j][x][y]); return ret; } int main(){ scanf ( "%d%d" ,&n,&K); if (!K) return puts ( "0" ),0; for (i=1;i<=n;i++) scanf ( "%d" ,&a[i]),a[i+n]=a[i]; if (n==3){ std::sort(a+1,a+n+1); for (i=n;i&&K;i--)ans+=a[i],K--; return printf ( "%d" ,ans),0; } K=std::min(K,n/2+5); K--; for (i=1;i<=2;i++){ for (m=0,j=i+1;j<i+n;j++)b[++m]=a[j]; up(ans,dp(1)+a[i]); } K++; for (m=0,i=3;i<=n;i++)b[++m]=a[i]; up(ans,dp(0)); return printf ( "%d" ,ans),0; } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 字符编码:从基础到乱码解决