T1:
.Double color chessboard 程序名称:dcc.pas/c/cpp 时间限制:2000ms 空间限制:8MB 题目描述 有一个游戏:给出一个n行n列的棋盘,里面有n*n个方格,其中每个格子上有颜色,总共 两种颜色0和1。 Bob要遵循规则去玩:一张卡要正好覆盖两个相邻且同色的正常格子。 我们的任务是帮助Bob知道棋盘在上述规则下能覆盖多少格子。 输入格式 第1行:整数n表示棋盘的长和宽。 第2行到第n+1行,有n个数,表示棋盘颜色。 输出格式 一个整数,表示能覆盖多少格子。 n<=300
坑点在于8M的空间,表示用一个unsigned short 和 char 代替 int 网络流跑。
发现wa了,原因在于二分图转流的时候不是加无向边。
#include<bits/stdc++.h> #define us unsigned short #define ma 60000 #define p(x,y) ((x)*301+(y)-1) using namespace std; struct Node{ us x; char op; int into() {return op*ma+x;} void out(int xx){op=xx/ma;x=xx%ma;} }; struct Maxflow{ #define N 97007 #define M 541007 #define eho(x) for(int i=head[x].into();i;i=net[i].into()) #define Eho(x) eho(x) #define inf 50007 int tim; int p[M]; Node fall[M],net[M],head[N],que[N]; int n,tot,s,t,be,ed,gap[N],d[N],x,ret; unsigned char cost[M]; Maxflow() {tot=1;} inline void add(int x,int y,int z){ fall[++tot].out(y); net[tot]=head[x]; head[x].out(tot); cost[tot]=z; } inline void Adds(int x,int y,int z){ add(x,y,z); add(y,x,z); } inline void adds(int x,int y,int z){ add(x,y,z); add(y,x,0); } void init() { ++gap[d[t]=1]; que[be=ed=1].out(t); while (be<=ed) { x=que[be++].into(); eho(x) if (!d[fall[i].into()]) ++gap[d[fall[i].into()]=d[x]+1],que[++ed]=fall[i]; } } us get(int x,int fl){ if (x==t) return fl; if (!fl) return 0; p[x]=tim; int flow=0,tmp; Eho(x) if (d[x]==d[fall[i].into()]+1&&(tmp=get(fall[i].into(),min(fl,(int)cost[i])))) { flow+=tmp; fl-=tmp; cost[i]-=tmp; cost[i^1]+=tmp; if (!fl) return flow; } if (!(--gap[d[x]])) d[s]=n+1; ++gap[++d[x]]; return flow; } int isap(int S,int T,int Siz){ s=S; t=T; n=Siz; init(); ++tim; ret=get(s,inf); while (d[s]<=n) ++tim,ret+=get(s,inf); return ret; } }G; int s=p(301,0),t=p(301,1),xx; int n; bitset<307> a[307]; signed main () { freopen("dcc.in","r",stdin); freopen("dcc.out","w",stdout); scanf("%d",&n); for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) scanf("%d",&xx),a[i][j]=xx; for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) { if ((i+j)&1) { G.adds(s,p(i,j),1); if (j<n&&a[i][j]==a[i][j+1]) G.adds(p(i,j),p(i,j+1),1); if (i<n&&a[i][j]==a[i+1][j]) G.adds(p(i,j),p(i+1,j),1); } else { G.adds(p(i,j),t,1); if (j<n&&a[i][j]==a[i][j+1]) G.adds(p(i,j+1),p(i,j),1); if (i<n&&a[i][j]==a[i+1][j]) G.adds(p(i+1,j),p(i,j),1); } } printf("%d ",G.isap(s,t,n*n+3)*2); }
T2:
题目描述 农场主Bob有无限的奶牛,奶牛分为A,B两种类型。现在Bob要选出N(2≤N≤10 15)头奶牛, 并把这N头奶牛围成一个环。为了美观且不单调,Bob希望任意相邻M(2≤M≤5,M≤N)头奶牛中 有不超过K(1≤K<M)头A类型的奶牛,其余奶牛均为B类型的奶牛。并且Bob想知道总共有多少 种不同的环。(结果 mod 1000000007)。 n<=1e15
快速幂。
#include<bits/stdc++.h> #define LL long long using namespace std; const int M=5,p=1000000007; LL n,m,k,ans; LL f[1<<M],a[1<<M][1<<M]; int MAX,cnt; bool pd[1<<M]; inline void mulself(LL a[1<<M][1<<M]) { LL c[1<<M][1<<M]; memset(c,0, sizeof c); for(int i=0;i<MAX;++i) for(int j=0;j<MAX;++j) for(int k=0;k<MAX;++k) c[i][j]=(c[i][j]+a[i][k]*a[k][j])%p; memmove(a,c,sizeof c); } inline void mul(LL f[1<<M],LL a[1<<M][1<<M]) { static LL c[1<<M]; memset(c,0,sizeof c); for(int j=0;j<MAX;++j) for(int k=0;k<MAX;++k) c[j]=(c[j]+f[k]*a[k][j])%p; memmove(f,c,sizeof c); } int main() { freopen("k.in","r",stdin); freopen("k.out","w",stdout); scanf("%lld%lld%lld",&n,&m,&k); MAX=1<<m; for(int i=0;i<MAX;++i) { cnt=0; for(int j=0;j<m;++j) if(i&1<<j) ++cnt; if(cnt<=k) pd[i]=true; } for(int i=0;i<MAX;++i) if(pd[i]) { memset(f,0,sizeof f);f[i]=1; memset(a,0,sizeof a); for(int j=0;j<MAX;++j) if(pd[j]){ a[j>>1][j]=1; a[(j>>1)+(1<<(m-1))][j]=1; } for(LL y=n;y;y>>=1,mulself(a)) if(y&1) mul(f,a); ans=(ans+f[i])%p; } printf("%lld ",ans); return 0; }
T3:
buyef 程序名称:buyef.pas/c/cpp 时间限制:2000ms 空间限制:32MB 问题描述 CQH想要潜入女生宿舍,因此他不但需要策划完美的潜入路线,更要购买一些女装进行掩 饰。 商店里总共有N(1≤N≤10 6)件女装,第i件女装的价格为Wi(1≤Wi≤300),萌值为 Vi(1≤Vi≤10 9)。 CQH有一个总预算K(1≤K≤10 5),他希望知道对于每个[1,k]中的整数i,如果他带了i 元,能买到的女装的萌值之和最大是多少。由于CQH正在策划路线,这个问题就交给你了。 输入格式 第一行N和K。 接下来N行,每行Wi和Vi。 输出格式 第一行K个数,第i个数表示带了i元时的答案。 20% N≤300; 100% 1≤N≤1000000 1≤Wi≤300; 1≤Vi≤100000 1≤K≤100000
对Wi分组sort,对每个Wi做决策分治。
#include<bits/stdc++.h> #define LL long long using namespace std; #define pb push_back #define N 1001007 int n,m,w,k,b,lo,o,VV,K; vector<LL> v[307]; LL f[2][N]; #define sight(c) ('0'<=c&&c<='9') inline void read(int &x){ static char c; for (c=getchar();!sight(c);c=getchar()); for (x=0;sight(c);c=getchar())x=x*10+c-48; } void write(LL x){if (x<10) {putchar('0'+x); return;} write(x/10); putchar('0'+x%10);} inline void writeln(LL x){ if (x<0) putchar('-'),x*=-1; write(x); putchar(' '); } inline void writel(LL x){ if (x<0) putchar('-'),x*=-1; write(x); putchar(' '); } void solve(int l,int r,int L,int R){ if (l>r) return ; int Mid=l+r>>1,d=Mid; LL tmp; f[o][Mid*k+b]=f[lo][Mid*k+b]; for (int i=min(R,Mid-1);i>=L;i--) { if (Mid-i>v[k].size()) break; if ((tmp=f[lo][i*k+b]+v[k][Mid-i-1])>f[o][Mid*k+b]) f[o][Mid*k+b]=tmp,d=i; } solve(l,Mid-1,L,d); solve(Mid+1,r,d,R); } int main () { freopen("buyef.in","r",stdin); freopen("buyed.out","w",stdout); read(n); read(m); for (int i=1;i<=n;i++){ read(w); read(VV); K=max(K,w); v[w].pb(VV); } // cerr<<"rrsb"<<K; for (int i=1;i<=K;i++) sort(v[i].begin(),v[i].end(),greater<LL>()); // cerr<<"rrsb"; for (int i=1;i<=K;i++) for (int j=1;j<v[i].size();j++) v[i][j]+=v[i][j-1]; o=1; for (k=1;k<=K;k++) { if (!v[k].size()) continue; for (b=0;b<k;b++) solve(0,(m-b)/k,0,(m-b)/k); for (int i=1;i<=m;i++) f[o][i]=max(f[o][i],f[o][i-1]); o^=1; lo^=1; } for (int i=1;i<=m;i++) writel(f[lo][i]); return 0; }