(A场因为不可抗力因素(?)没能参加,B场还好算是磕磕碰碰地吃着低保过去了,真的菜呀)
可以说还是比较一目了然的签到题,由于这些点的横纵坐标都必须严格递增,那么我们最多能取到的点就是 min(n,m) 个;方案数就相当于是在 max(n,m) 中选 min(n,m) 个的方案数,那么答案就是 C(max(n,m),min(n,m)) 了。
留意数据范围,用杨辉三角预处理答案就可以了(先写lucas定理再写拓欧的我大概是失了智)。
这题大概是数据没出好?据说 T∗n2∗logn 的暴力也能过233
正解没什么头绪,留坑待填(据jiangshibiao大神说是根据集合大小分开处理orz)
这道题的题意实际上是问我们一个含有一定数量ABCD且相邻字符不相等的序列有多少个。一个 n4 的TLE解法很快就能想出来了:用每个字符已经出现的次数和最后一个字符表示状态,然后再瞎dp一番。
至于正解,我们其实可以用一种类似于小朋友们学组合数学时用的“插板”的理解方式来理解这个过程。我们每一次把所有的某种字符摆放到原有的字符的中间,那么这个过程中,就会有一些原本的连续相同字符段被分隔开,有一些新的连续相同字符段产生。由于每次放置一种字符,所统计的每种方案字符相对位置有所不同,所以不会出现重复统计的情况。可以用 f[i][j] 表示已经放了i种字符,还存在j个连续相同字符段的方案数, f[i] 数组和 f[i−1] 之间存在递推关系(好像有点麻烦先挖个坑)。
(时间复杂度大概是 O(n2) ?)(感谢dhr小朋友)
是一道相当友好的网络流裸题了。S向每个片区连费用为 a[i] 容量为 b[i] 的边,片区间连费用为0容量为无穷大的边,每个片区向T连费用为 −c[i] 容量为 d[i] 的边。图显然不会出现负环,直接跑一个spfa的最小费用流即可(增广到费用不小于零的路径就停止)。
#include
#include
#include
#include
#define inf 0x7f7f7f7f
using namespace std;
int d[1010],dis[510][510],n,m,a[1010],to[2000010],nxt[2000010],cap[2000010],path[1010],cnt,S,T;
bool inq[1010],boo[510][510];
void addedge(int u,int v,int c){
to[++cnt]=v;nxt[cnt]=a[u];cap[cnt]=c;a[u]=cnt;
}
int SPFA(){
queue<int> q;
memset(d,0x7f,sizeof(d));
memset(inq,0,sizeof(inq));
memset(path,0,sizeof(path));
q.push(S);
d[S]=0;inq[S]=1;
while (!q.empty()){
int x=q.front();q.pop();inq[x]=0;
for (int i=a[x];i;i=nxt[i]){
int y=to[i];
int cost=dis[x][y];
if (i%2) cost=-cost;
if (cap[i]>0&&d[x]+costy]){
d[y]=d[x]+cost;
path[y]=i;
if (inq[y])continue;
q.push(y);
inq[y]=1;
}
}
}
return d[T];
}
int flow(){
int p=T,f=inf;
while (p!=S){
f=min(f,cap[path[p]]);
p=to[path[p]^1];
}
p=T;
while (p!=S){
cap[path[p]]-=f;
cap[path[p]^1]+=f;
p=to[path[p]^1];
}
return f;
}
void solve(){
S=0;T=n+1;cnt=1;
memset(a,0,sizeof(a));
memset(nxt,0,sizeof(nxt));
memset(dis,0x7f,sizeof(dis));
memset(boo,0,sizeof(boo));
for (int i=1;i<=n;i++){
int A,B,C,D;
scanf("%d%d%d%d",&A,&B,&C,&D);
dis[i][T]=dis[T][i]=A;
dis[S][i]=dis[i][S]=-C;
addedge(i,T,B);
addedge(T,i,0);
addedge(S,i,D);
addedge(i,S,0);
}
for (int i=1;i<=m;i++){
int u,v,k;
scanf("%d%d%d",&u,&v,&k);
if (u==v) continue;
if (!boo[u][v]) {
boo[u][v]=boo[v][u]=1;
addedge(u,v,inf);
addedge(v,u,0);
addedge(v,u,inf);
addedge(u,v,0);
}
dis[u][v]=min(dis[u][v],k);
dis[v][u]=dis[u][v];
}
int ret=0,dist;
while (dist=SPFA()) {
if (dist>=0) break;
ret-=flow()*dist;
}n",ret); } int main(){ while(scanf("%d%d",&n,&m)!=EOF) solve(); }
丑陋的代码。
简单签到题,先预处理出不重叠的区间,再维护连续的一段看看能不能被m天相连,最后处理多余的补签卡即可。
实话说这场比赛收获不大……但为了有个好的新开始还是决定写一篇口胡总结,毕竟得打回些状态啊QAQ。