省选模拟23
今天的题确实是有技术含量,我改到现在才(21:00)改完
以为自己要垫底了,zxb上来就开打,但是我发现第一题并不是很容易做的
于是半个小时之后转战第二题,发现是个插头dp,于是写完之后就知道自己T飞了
弃掉干T3,然而只会第一个部分分,也就是暴力分
T1 高维游走
能看出来是个背包,用那个啥啥(库默尔)定理,得到后面所有选择是t0的二进制划分,与ti是自己
于是我们可以直接做背包,这样的话是值域的
我们想要合并背包,考场上没有想出来太好的办法,于是就鸽掉了
发现当前位只会受到这一位的选择和之前的进位的影响,那么我们想要记录最后一位剩下多少并且和后面合并
有一点dp套dp的意思
我们直接记录最后一位是x的数有多少个数是合法的
但是我们发现这样记录好像没有办法转移诶!!???毕竟我们不知道这里面和别的重复的有多少
于是我们想把最后一位是0~m的都表示出来,而这个任何数的范围很小(最多进m位好吧),可以二进制
我们用某一个二进制的状态表示当前状态下的合法的数有多少个,这样转移也是一起转移,就不怕记重了......
AC_code
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
int s=0,t=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();}
return s*t;
}
int T,n,u;ll t[15];
ll f[40][1<<11];
int zy[15][1<<11];
pair<int,int> ok[1<<21];
signed main(){
freopen("travel.in","r",stdin);
freopen("travel.out","w",stdout);
T=read();
fo(i,0,10){
fo(s,0,(1<<11)-1){
fo(j,0,10){
if(!(s>>j&1))continue;
zy[i][s]^=(1ll<<j+i);
}
}
}
fo(s,0,(1<<21)-1){
int ss1=0,ss2=0;
fo(j,0,20)if(s>>j&1){
if(j&1)ss1|=(1ll<<(j>>1));
else ss2|=(1ll<<(j>>1));
}
ok[s]=make_pair(ss1,ss2);
}
while(T--){
n=read();fo(i,0,n)t[i]=read();
f[0][1]=1;u=(1<<n+1)-1;
fo(i,0,34){
if(!(t[0]>>i&1)){
fo(s,0,u){int buc=0;
fo(i,0,n)if(s>>i&1)buc^=(1<<i);
int ss1=ok[buc].first,ss2=ok[buc].second;
if(ss1)f[i+1][ss1]+=f[i][s];
if(ss2)f[i+1][ss2]+=f[i][s];
}
continue;
}
fo(s,0,u){int buc=0;
fo(k,0,n){
if(!(t[k]>>i&1))continue;
buc^=zy[k][s];
}
int ss1=ok[buc].first,ss2=ok[buc].second;
if(ss1)f[i+1][ss1]+=f[i][s];
if(ss2)f[i+1][ss2]+=f[i][s];
}
}
printf("%lld\n",f[35][1]);
fo(i,0,35)fo(s,0,u)f[i][s]=0;
}
}
T2 过山车
正解竟然是网络流,发现一个规律,网格图是可以黑白染色变成二分图的
并且一般网络流的图就考虑正着最大和总的减去反着最小......
这个就是总的减去反着最小,我们跑最小费用最大流就好了
AC_code
#include<bits/stdc++.h>
using namespace std;
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
int s=0,t=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();}
return s*t;
}
const int N=6005;
const int inf=0x3f3f3f3f;
struct E{int to,nxt,val,cot;}e[N*25];
int head[N*3],rp=1,s=4500*3+1,t=4500*3+2;
void add_edg(int x,int y,int z,int w){
e[++rp].to=y;e[rp].nxt=head[x];
e[rp].val=z;e[rp].cot=w;head[x]=rp;
}
int dis[N*3],pre[N*3],epr[N*3],flo[N*3];
bool vis[N*3];
bool spfa(){
memset(dis,0x3f,sizeof(dis));
queue<int> q;while(!q.empty())q.pop();
q.push(s);dis[s]=0;flo[s]=inf;
while(!q.empty()){
int x=q.front();q.pop();vis[x]=false;
for(int i=head[x];i;i=e[i].nxt){
int y=e[i].to;
if(dis[y]<=dis[x]+e[i].cot||!e[i].val)continue;
dis[y]=dis[x]+e[i].cot;
flo[y]=min(flo[x],e[i].val);
pre[y]=x;epr[y]=i;
if(!vis[y])q.push(y),vis[y]=true;
}
}
return dis[t]!=inf;
}
pair<int,int> netflow(){
int sum=0,cos=0;
while(spfa()){
int now=t;
sum+=flo[t];cos+=dis[t];
while(now!=s){
e[epr[now]].val-=flo[t];
e[epr[now]^1].val+=flo[t];
now=pre[now];
}
}
return make_pair(sum,cos);
}
int n,m,jz[155][35],w[155][35];
int all,wll,id[155][35],cid;
bool jud(int x,int y){return (x<=n&&x&&y<=m&&y&&jz[x][y]);}
signed main(){
freopen("roller.in","r",stdin);
freopen("roller.out","w",stdout);
n=read();m=read();
fo(i,1,n)fo(j,1,m)jz[i][j]=read()^1;
fo(i,1,n)fo(j,1,m)w[i][j]=read();
fo(i,1,n)fo(j,1,m){
if(jz[i][j]){
id[i][j]=++cid;
cid+=2;wll+=w[i][j];
}
}
fo(i,1,n)fo(j,1,m){
if(!jz[i][j])continue;
if(i+j&1){
all+=2;//cerr<<i<<" "<<j<<endl;
add_edg(s,id[i][j],2,0);
add_edg(id[i][j],s,0,0);
add_edg(id[i][j],id[i][j]+1,1,0);
add_edg(id[i][j]+1,id[i][j],0,0);
add_edg(id[i][j],id[i][j]+1,1,w[i][j]);
add_edg(id[i][j]+1,id[i][j],0,-w[i][j]);
add_edg(id[i][j],id[i][j]+2,1,0);
add_edg(id[i][j]+2,id[i][j],0,0);
add_edg(id[i][j],id[i][j]+2,1,w[i][j]);
add_edg(id[i][j]+2,id[i][j],0,-w[i][j]);
if(jud(i+1,j)){
add_edg(id[i][j]+1,id[i+1][j]+1,1,0);
add_edg(id[i+1][j]+1,id[i][j]+1,0,0);
}
if(jud(i-1,j)){
add_edg(id[i][j]+1,id[i-1][j]+1,1,0);
add_edg(id[i-1][j]+1,id[i][j]+1,0,0);
}
if(jud(i,j+1)){
add_edg(id[i][j]+2,id[i][j+1]+2,1,0);
add_edg(id[i][j+1]+2,id[i][j]+2,0,0);
}
if(jud(i,j-1)){
add_edg(id[i][j]+2,id[i][j-1]+2,1,0);
add_edg(id[i][j-1]+2,id[i][j]+2,0,0);
}
}
else {
add_edg(id[i][j],t,2,0);
add_edg(t,id[i][j],0,0);
add_edg(id[i][j]+1,id[i][j],1,0);
add_edg(id[i][j],id[i][j]+1,0,0);
add_edg(id[i][j]+1,id[i][j],1,w[i][j]);
add_edg(id[i][j],id[i][j]+1,0,-w[i][j]);
add_edg(id[i][j]+2,id[i][j],1,0);
add_edg(id[i][j],id[i][j]+2,0,0);
add_edg(id[i][j]+2,id[i][j],1,w[i][j]);
add_edg(id[i][j],id[i][j]+2,0,-w[i][j]);
}
}
pair<int,int> ret=netflow();
//cerr<<ret.first<<" "<<ret.second<<endl;
if(ret.first!=all)printf("-1");
else printf("%d",wll-ret.second);
}
T3 木棍
原来是差分约束!!!
用前缀和记录有多少个左端点
然后差分约束就行了
AC_code
#include<bits/stdc++.h>
using namespace std;
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
int s=0,t=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();}
return s*t;
}
const int N=10005;
int n,k,m;
struct E{int to,nxt,val;}e[20000000];
int head[N],rp;
void add_edg(int x,int y,int z){
// cerr<<x<<" "<<y<<" "<<z<<endl;
e[++rp].to=y;e[rp].nxt=head[x];
e[rp].val=z;head[x]=rp;
}
int dis[N],cnt[N];
bool vis[N];
int lsh[N],lh;
struct STI{int a,b;}sti[N];
struct LIM{int a,b,c;}lim[N];
set<int> st;
vector<int> bg[N],ed[N];
struct node{
int x,ds;
bool operator < (node a)const{
return ds>a.ds;
}
};
priority_queue<node> q;
signed main(){
freopen("stick.in","r",stdin);
freopen("stick.out","w",stdout);
n=read();m=read();k=read();
fo(i,1,n){sti[i].a=read();sti[i].b=read()+1-k;lsh[++lh]=sti[i].a;lsh[++lh]=sti[i].b;}
fo(i,1,m){lim[i].a=read();lim[i].b=read()+1-k;lim[i].c=read();lsh[++lh]=lim[i].a;lsh[++lh]=lim[i].b;}
sort(lsh+1,lsh+lh+1);lh=unique(lsh+1,lsh+lh+1)-lsh-1;
fo(l,1,lh-1)fo(r,l+1,lh){
add_edg(l,r,((lsh[r]-lsh[l]-1)/k+1));
}
fo(i,1,n){
int a=lower_bound(lsh+1,lsh+lh+1,sti[i].a)-lsh;
int b=lower_bound(lsh+1,lsh+lh+1,sti[i].b)-lsh;
bg[a].push_back(i);ed[b].push_back(i);
}
fo(l,1,lh){
int sum=0;st.clear();
fo(r,l,lh){
for(int i:bg[r])st.insert(i);
for(int i:ed[r])if(st.find(i)!=st.end())sum++,st.erase(i);//cerr<<i<<endl;
add_edg(r,l,-sum);
}
}
fo(i,1,m){
int l=lower_bound(lsh+1,lsh+lh+1,lim[i].a)-lsh;
int r=lower_bound(lsh+1,lsh+lh+1,lim[i].b)-lsh;
add_edg(l,r,lim[i].c);
}
memset(dis,0x3f,sizeof(dis));
q.push(node{1,0});dis[1]=0;cnt[1]=1;
while(!q.empty()){
int x=q.top().x;q.pop();vis[x]=false;
if(1.0*clock()/CLOCKS_PER_SEC>=0.6){printf("No");return 0;}
for(int i=head[x];i;i=e[i].nxt){
int y=e[i].to;
if(dis[y]<=dis[x]+e[i].val)continue;
dis[y]=dis[x]+e[i].val;
if(cnt[y]>lh){printf("No");return 0;}
if(!vis[y])q.push(node{y,dis[y]}),vis[y]=true;
}
}
printf("Yes");
}
QQ:2953174821