A:题意: 有一个n个点的圈标号为0-n-1 每次只能向相邻方向走一步 两个方向随机 每走到一个新的格子都会设立一个标记 (一开始在0设立标记) 问最后停在第m个格子的概率为多少 输出答案积
概率为1/(n-1) 注意m为0的特殊情况即可
#include<bits/stdc++.h> using namespace std; //input by bxd #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define repp(i,a,b) for(int i=(a);i>=(b);--i) #define RI(n) scanf("%d",&(n)) #define RII(n,m) scanf("%d%d",&n,&m) #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k) #define RS(s) scanf("%s",s); #define ll long long #define pb push_back #define inf 0x3f3f3f3f #define CLR(A,v) memset(A,v,sizeof A) ////////////////////////////////// const int N=101; const ll mod=1e9+7; ll fast(ll x,ll n){ll ans=1;while(n){if(n&1)ans*=x,ans%=mod;x*=x;x%=mod;n>>=1 ; }return ans; } ll n,m; int main() { ll ans=1;int cas;RI(cas); while(cas--) { scanf("%lld%lld",&n,&m); ll res; if(m==0)res=(n>1)?0:1; else res=fast(n-1,mod-2); ans*=res,ans%=mod; cout<<ans<<endl; } return 0; }
D:给出一个无向点权图 问点权第k大的团的点权为多少
bfs遍历即可 设置一个点权优先队列
使用bitset来表示路径和 包含点 非常方便
#include<bits/stdc++.h> using namespace std; //input by bxd #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define repp(i,a,b) for(int i=(a);i>=(b);--i) #define RI(n) scanf("%d",&(n)) #define RII(n,m) scanf("%d%d",&n,&m) #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k) #define RS(s) scanf("%s",s); #define ll long long #define pb push_back #define inf 0x3f3f3f3f #define CLR(A,v) memset(A,v,sizeof A) ////////////////////////////////// const int N=101; struct node { ll sum; int id; bitset<N>s; bool operator < (const node & b)const { return sum>b.sum; } }; int n,k,v[N]; char ss[N]; bitset<N>e[N]; ll sol() { RII(n,k); rep(i,1,n)RI(v[i]); rep(i,1,n) { RS(ss+1); rep(j,1,n) { if(ss[j]=='1')e[i].set(j); } } bitset<N>s; s.reset(); priority_queue<node>q; q.push(node{0,0,s}); while(!q.empty()) { node u=q.top();q.pop(); if(--k==0)return u.sum; rep(i,u.id+1,n) { if(!u.s[i]&&(u.s&e[i])==u.s) { u.s.set(i); q.push(node{u.sum+1ll*v[i],i,u.s }); u.s.reset(i); } } } return -1; } int main() { printf("%lld",sol()); }
E:
给出一个nm 01矩阵 (迷宫) 1代表墙不能走
操作一 将x行y列 这个点反转
操作二 问第一行的x点到第n行的y点的路径个数
用矩阵乘法来计算路径个数 用线段树来维护
#include<bits/stdc++.h> using namespace std; //input by bxd #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define repp(i,a,b) for(int i=(a);i>=(b);--i) #define RI(n) scanf("%d",&(n)) #define RII(n,m) scanf("%d%d",&n,&m) #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k) #define RS(s) scanf("%s",s); #define ll long long #define pb push_back #define inf 0x3f3f3f3f #define lson l,m,pos<<1 #define rson m+1,r,pos<<1|1 #define CLR(A,v) memset(A,v,sizeof A) ////////////////////////////////// const int N=1e4; const int mod=1e9+7; int n,m,q,b[50000+10][11]; struct Matrix { ll a[11][11]; friend Matrix operator*(const Matrix &a,const Matrix &b) { Matrix c;CLR(c.a,0); rep(i,1,m)rep(k,1,m)rep(j,1,m) c.a[i][j]=(c.a[i][j]+1ll*a.a[i][k]*b.a[k][j])%mod; return c; } } t[200000+10]; void change(int *b,Matrix &ans) { CLR(ans.a,0); rep(i,1,m) { int j=i; for(;j>=1&&!b[j];ans.a[i][j]=1,--j); j=i; for(;j<=m&&!b[j];ans.a[i][j]=1,j++); } } void build(int l,int r,int pos) { if(l==r){change(b[l],t[pos]);return ;} int m=(l+r)>>1;build(lson);build(rson); t[pos]=t[pos<<1]*t[pos<<1|1]; } void up(int x,int l,int r,int pos) { if(l==r){change(b[l],t[pos]);return ; } int m=(l+r)>>1; if(x<=m)up(x,lson); else if(x>m)up(x,rson); t[pos]=t[pos<<1]*t[pos<<1|1]; } char s[100]; int main() { scanf("%d%d%d",&n,&m,&q); rep(i,1,n){scanf("%s",s+1);rep(j,1,m)b[i][j]=s[j]-'0';} build(1,n,1); while(q--) { ll op,x,y; scanf("%lld%lld%lld",&op,&x,&y); if(op==1)b[x][y]^=1,up(x,1,n,1); else if(op==2)printf("%lld ",t[1].a[x][y]); } }
F:
有2*n个人 和两个队伍 将这2*n个人分配到两个队伍使得每个队伍恰好n个人
如果两个人分配到两个队伍会产生一个冲突mp[i][j](条件给出) 问能产生的最大冲突
dfs
如果dfs找到n个后再计算贡献呢的话复杂度为 C(2n,n) *n2
可以边dfs边计算贡献 那么复杂度可以减一个n
#include<bits/stdc++.h> using namespace std; //input by bxd #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define repp(i,a,b) for(int i=(a);i>=(b);--i) #define RI(n) scanf("%d",&(n)) #define RII(n,m) scanf("%d%d",&n,&m) #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k) #define RS(s) scanf("%s",s); #define ll long long #define pb push_back #define inf 0x3f3f3f3f #define CLR(A,v) memset(A,v,sizeof A) ////////////////////////////////// const int N=1001; ll sum[N],mp[N][N],ans,ans1,vis[N]; int n; void dfs(int cur,int num) { if(num==n+1) { ans=max(ans,ans1);return ; } rep(i,cur+1,2*n) { ll k=ans1; vis[num]=i; ans1+=sum[i]; rep(j,1,num-1) ans1-=mp[i][vis[j]]*2; dfs(i,num+1); ans1=k; } } int main() { RI(n); rep(i,1,2*n)rep(j,1,2*n)scanf("%lld",&mp[i][j]),sum[i]+=mp[i][j]; dfs(0,1); cout<<ans; return 0; }
H
求第二大矩形
比赛的时候扣四个点分别dp
也可以用单调栈来维护
#include<bits/stdc++.h> using namespace std; //input by bxd #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define repp(i,a,b) for(int i=(a);i>=(b);--i) #define RI(n) scanf("%d",&(n)) #define see(x) (cerr<<(#x)<<'='<<(x)<<endl) #define RII(n,m) scanf("%d%d",&n,&m) #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k) #define RS(s) scanf("%s",s); #define ll long long #define REP(i,N) for(int i=0;i<(N);i++) #define CLR(A,v) memset(A,v,sizeof A) #define inf 0x3f3f3f3f ////////////////////////////////// const int N=1000+5; int dp[N][N]; char mp[N][N]; int ri[N][N],le[N][N],up[N][N]; int main() { int s; int n,m; RII(n,m); rep(i,1,n)RS(mp[i]+1); rep(i,1,n) rep(j,1,m) { if(mp[i][j]=='1')mp[i][j]=1; else mp[i][j]=0; ri[i][j]=le[i][j]=j; up[i][j]=1; } rep(i,1,n) rep(j,2,m) if(mp[i][j]==mp[i][j-1]&&mp[i][j]==1) le[i][j]=le[i][j-1]; rep(i,1,n) repp(j,m-1,1) if(mp[i][j]==mp[i][j+1]&&mp[i][j]==1) ri[i][j]=ri[i][j+1]; int ans=0,maxx=0; int flagx=-1,flagy=-1; int chang,gao; rep(i,1,n) rep(j,1,m) if(mp[i][j]) { if(i>1) if(mp[i-1][j])//如果状态需要转移的话 { le[i][j]=max(le[i][j],le[i-1][j]); ri[i][j]=min(ri[i][j],ri[i-1][j]); up[i][j]=up[i-1][j]+1; } int d=ri[i][j]-le[i][j]+1; if(d*up[i][j]>maxx) { maxx=d*up[i][j]; s=d*up[i][j]; flagx=i;flagy=j; chang=d;gao=up[i][j]; ans=max(s-d,s-(s/d)); } } int x1,yy,x2,y2,x3,y3,x4,y4; //see(flagx);see(flagy);see(chang);see(gao); int shang=flagx-gao+1; int L=0,R=inf; //see(shang); rep(i,shang,flagx) { int l=flagy,r=flagy; while(mp[i][l-1]==1&&l-1>=1)l--; while(mp[i][r+1]==1&&r+1<=m)r++; L=max(L,l); R=min(R,r); } //see(L);see(R); x1=x2=shang; x3=x4=flagx; yy=L;y2=R; y3=L;y4=R; //see(x1);see(yy);see(x2);see(y2);see(x3);see(y3);see(x4);see(y4); maxx=0; mp[x1][yy]=0; rep(i,1,n) rep(j,1,m) { ri[i][j]=le[i][j]=j; up[i][j]=1; } rep(i,1,n) rep(j,2,m) if(mp[i][j]==mp[i][j-1]&&mp[i][j]==1) le[i][j]=le[i][j-1]; rep(i,1,n) repp(j,m-1,1) if(mp[i][j]==mp[i][j+1]&&mp[i][j]==1) ri[i][j]=ri[i][j+1]; rep(i,1,n) rep(j,1,m) if(mp[i][j]) { if(i>1) if(mp[i-1][j])//如果状态需要转移的话 { le[i][j]=max(le[i][j],le[i-1][j]); ri[i][j]=min(ri[i][j],ri[i-1][j]); up[i][j]=up[i-1][j]+1; } int d=ri[i][j]-le[i][j]+1; s=d*up[i][j]; maxx=max(maxx,s); } mp[x1][yy]=1; mp[x2][y2]=0; rep(i,1,n) rep(j,1,m) { ri[i][j]=le[i][j]=j; up[i][j]=1; } rep(i,1,n) rep(j,2,m) if(mp[i][j]==mp[i][j-1]&&mp[i][j]==1) le[i][j]=le[i][j-1]; rep(i,1,n) repp(j,m-1,1) if(mp[i][j]==mp[i][j+1]&&mp[i][j]==1) ri[i][j]=ri[i][j+1]; rep(i,1,n) rep(j,1,m) if(mp[i][j]) { if(i>1) if(mp[i-1][j])//如果状态需要转移的话 { le[i][j]=max(le[i][j],le[i-1][j]); ri[i][j]=min(ri[i][j],ri[i-1][j]); up[i][j]=up[i-1][j]+1; } int d=ri[i][j]-le[i][j]+1; s=d*up[i][j]; maxx=max(maxx,s); } mp[x2][y2]=1; mp[x3][y3]=0; rep(i,1,n) rep(j,1,m) { ri[i][j]=le[i][j]=j; up[i][j]=1; } rep(i,1,n) rep(j,2,m) if(mp[i][j]==mp[i][j-1]&&mp[i][j]==1) le[i][j]=le[i][j-1]; rep(i,1,n) repp(j,m-1,1) if(mp[i][j]==mp[i][j+1]&&mp[i][j]==1) ri[i][j]=ri[i][j+1]; rep(i,1,n) rep(j,1,m) if(mp[i][j]) { if(i>1) if(mp[i-1][j])//如果状态需要转移的话 { le[i][j]=max(le[i][j],le[i-1][j]); ri[i][j]=min(ri[i][j],ri[i-1][j]); up[i][j]=up[i-1][j]+1; } int d=ri[i][j]-le[i][j]+1; s=d*up[i][j]; maxx=max(maxx,s); } mp[x3][y3]=1; mp[x4][y4]=0; rep(i,1,n) rep(j,1,m) { ri[i][j]=le[i][j]=j; up[i][j]=1; } rep(i,1,n) rep(j,2,m) if(mp[i][j]==mp[i][j-1]&&mp[i][j]==1) le[i][j]=le[i][j-1]; rep(i,1,n) repp(j,m-1,1) if(mp[i][j]==mp[i][j+1]&&mp[i][j]==1) ri[i][j]=ri[i][j+1]; rep(i,1,n) rep(j,1,m) if(mp[i][j]) { if(i>1) if(mp[i-1][j])//如果状态需要转移的话 { le[i][j]=max(le[i][j],le[i-1][j]); ri[i][j]=min(ri[i][j],ri[i-1][j]); up[i][j]=up[i-1][j]+1; } int d=ri[i][j]-le[i][j]+1; s=d*up[i][j]; maxx=max(maxx,s); } mp[x4][y4]=1; printf("%d ",maxx); return 0; }