20190912

A1 100pts

考试时暴力打表+发现三次函数于是暴力解方程。
更好的:
发现是在枚举子矩形并求面积,于是有:

\(\sum_{x}^n\sum_{y}^m x * y \times (n-x+1) * (m-y+1)\)
\(f(x)=\sum_{x}^n x * (n-x+1)\)
\(=1*n + 2*(n-1) + 3*(n-2) + \cdots + (n-1)*2 + n*1\)
\(=\frac{(n+1)*n*n*3}{6} - (1*2+2*3+3*4+\cdot +(n-1)*n)\)
\(=\frac{(n+1)*n*n*3}{6} - \sum_{i} i*(i-1)\)
\(=\frac{(n+1)*n*n*3}{6} - \sum_{i} i^2-i\)
\(=\frac{(n+1)*n*n*3}{6} - \frac{n*(n+1)*(2*n+1)}{6} + \frac{n*(n+1)*3}{6}\)
\(=\frac{(n+1)*n*(3*n-(2*n+1)+3}{6}\)
\(=\frac{n*(n+1)*(n+2)}{6}\)

#include<bits/stdc++.h>
#define ll long long
#define R register ll
using namespace std;
namespace Luitaryi {
inline ll g() { R x=0,f=1;
  register char ch; while(!isdigit(ch=getchar())) f=ch=='-'?-1:f;
  do x=x*10+(ch^48); while(isdigit(ch=getchar())); return x*f;
} const ll Inv2=500000004,Inv3=333333336,M=1000000007;
ll n,m;
inline void main() {
  n=g(),m=g(); n%=M,m%=M;
  printf("%lld\n",n*(n+1)%M*Inv2%M*(n+2)%M*Inv3%M*m%M*(m+1)%M*Inv2%M*(m+2)%M*Inv3%M);
}
} signed main() {Luitaryi::main(); return 0;}

A2 100pts

二分,枚举三个边界,二分第四个边界。

#include<bits/stdc++.h>
#define ll long long
#define R register int
using namespace std;
namespace Luitaryi {
inline int g() { R x=0,f=1;
  register char ch; while(!isdigit(ch=getchar())) f=ch=='-'?-1:f;
  do x=x*10+(ch^48); while(isdigit(ch=getchar())); return x*f;
} const int N=310;
int n,m,ans,q[N];
ll a[N][N];
inline void main() { 
  n=g(),m=g(); 
  for(R i=1;i<=n;++i) for(R j=1;j<=m;++j) a[i][j]=g();
  for(R i=1;i<=n;++i) for(R j=1;j<=m;++j) a[i][j]+=a[i][j-1];
  for(R i=1;i<=n;++i) for(R j=1;j<=m;++j) a[i][j]+=a[i-1][j];
  for(R i=1;i<=n;++i) for(R j=i;j<=n;++j) {
    R t=0; register ll tmp;
    for(R p=1;p<=m;++p) { 
      if(t) tmp=a[j][p-1]-a[j][q[t]-1]-a[i-1][p-1]+a[i-1][q[t]-1]; else tmp=-1;
      if(tmp<0) q[++t]=p; 
      R l=1,r=t+1,md,pos; while(l<r) {
        md=l+r>>1,pos=q[md];
        if(a[j][p]-a[j][pos-1]-a[i-1][p]+a[i-1][pos-1]>0) r=md;
        else l=md+1;
      } if(l<t+1) { l=q[l];
        ans=max(ans,(j-i+1)*(p-l+1));
      }
    }
  } printf("%d\n",ans);
}
} signed main() {Luitaryi::main(); return 0;}

A3 20pts

OTZ ZBK && LQS

贪心:(真是应该多想想)
显然先排序,显然先魔法;
如何选择重 or 众:
若有一个血量为1或大于2个,众;
否则,重;
OTZ想不到想不到(其实当时想了想好像跟数量有关但是不会证QwQ)

#include<bits/stdc++.h>
#define ll long long
#define R register int
using namespace std;
namespace Luitaryi {
inline int g() { R x=0,f=1;
  register char ch; while(!isdigit(ch=getchar())) f=ch=='-'?-1:f;
  do x=x*10+(ch^48); while(isdigit(ch=getchar())); return x*f;
} const int N=100010;
int n,m,a[N];
inline void main() {
  n=g(),m=g(); for(R i=1;i<=n;++i) a[i]=g();
  sort(a+1,a+n+1); register ll ans=0,pos=1,add=0;
  while(pos<=n) {
    if(!m) {
      for(R i=pos;i<=n;++i) ans+=(a[i]-add-1)*(n-i+1)+n-i; 
      break;
    } if((a[pos]-add==1||n-pos+1>2)&&m) ++add,--m;
    else if(m) a[pos]-=2,--m;
    else --a[pos];
    while(a[pos]<=add&&pos<=n) ++pos; ans+=n-pos+1; 
  } printf("%lld\n",ans);
}
} signed main() {Luitaryi::main(); return 0;}

B1

暴力匹配???惊了 \(n\leq 3000\)
开一个map建立单射,并开一个 \(bool vis[]\) 判种类(暂时没有反例)

#include<bits/stdc++.h>
#define R register int
using namespace std;
namespace Luitaryi {
inline int g() { R x=0,f=1;
	register char ch; while(!isdigit(ch=getchar())) f=ch=='-'?-1:f;
	do x=x*10+(ch^48); while(isdigit(ch=getchar())); return x*f;
} const int N=2010;
unordered_map<int,int> mp; bool vis[N];
int n,m,c,a[N],b[N],ans[N],cnt,tot;
inline void main() {
	n=g(),m=g(),c=g(); for(R i=1;i<=n;++i) a[i]=g();
	for(R i=0;i<m;++i) b[i]=g(),tot+=(!vis[b[i]]),vis[b[i]]=true;
	for(R i=1;i<=n-m+1;++i) { 
		memset(vis,0,sizeof vis),c=0;
		for(R j=0;j<m;++j) { 
			c+=(!vis[a[i+j]]),vis[a[i+j]]=true;
			if(mp.count(b[j])) { 
				if(mp[b[j]]==a[i+j]) continue;	
				else goto end;
			} else mp[b[j]]=a[i+j];
		} if(c>=tot) ans[++cnt]=i; end:mp.clear();
	} printf("%d\n",cnt);
	for(R i=1;i<=cnt;++i) printf("%d ",ans[i]);
}
} signed main() {Luitaryi::main(); return 0;}

B2

这个DP。。。想不到想不到ORZ
发现它既不能按位置直接DP,又不能按时间轴DP。
于是类似区间DP:\(f[l][r][0/1]\)表示 \([1,l]\)\([r,n]\) 的案件已经处理完毕
这样就可以愉快的转移了。

#include<bits/stdc++.h>
#define R register int
using namespace std;
namespace Luitaryi {
inline int g() { R x=0,f=1;
  register char ch; while(!isdigit(ch=getchar())) f=ch=='-'?-1:f;
  do x=x*10+(ch^48); while(isdigit(ch=getchar())); return x*f;
} const int N=1010,Inf=0x3f3f3f3f;
struct node { int d,t;
  inline bool operator < (const node& that) const {return d<that.d;}
}a[N]; int n,H,B,f[N][N][2],ans=Inf; 
inline void main() {
  n=g(),H=g(),B=g(); for(R i=1;i<=n;++i) a[i].d=g(),a[i].t=g();
  sort(a+1,a+n+1); 
  f[1][n][0]=max(a[1].t,a[1].d),
  f[1][n][1]=max(a[n].d,a[n].t);
  for(R len=n-2;~len;--len) for(R i=1;i+len<=n;++i) { R l=i,r=i+len;
    f[l][r][0]=f[l][r][1]=Inf;
    if(r<n) 
      f[l][r][1]=min(f[l][r][1],f[l][r+1][1]+a[r+1].d-a[r].d),
      f[l][r][0]=min(f[l][r][0],f[l][r+1][1]+a[r+1].d-a[l].d);
    if(l>1) 
      f[l][r][1]=min(f[l][r][1],f[l-1][r][0]+a[r].d-a[l-1].d),
      f[l][r][0]=min(f[l][r][0],f[l-1][r][0]+a[l].d-a[l-1].d);
      f[l][r][1]=max(f[l][r][1],a[r].t);
      f[l][r][0]=max(f[l][r][0],a[l].t);
  } for(R i=1;i<=n;++i) 
    ans=min(ans,min(f[i][i][0],f[i][i][1])+abs(a[i].d-B));
  printf("%lld\n",ans);
}
} signed main() {Luitaryi::main(); return 0;}

B3 咕咕咕

A组比B组简单系列

还好我做的A组

posted @ 2019-09-16 19:16  LuitaryiJack  阅读(360)  评论(1编辑  收藏  举报