題意:求一個矩陣的全部子矩陣的與和 和 或和。dom
分析:ui
代碼:spa
#include <cstdio> #include <cstring> #include <algorithm> #include <cstdlib> using namespace std; typedef long long ll; #define N 1050 #define mod 1000000007 int mask=(1ll<<31)-1,n,a[N][N]; int b[N][N],up[N],S[N],tp; ll work() { int i,j,k; ll re=0; for(k=0;k<=30;k++) { for(i=1;i<=n;i++) up[i]=0; for(i=1;i<=n;i++) { ll now=0; tp=0; S[0]=0; for(j=1;j<=n;j++) { b[i][j]=a[i][j]&(1<<k); if(!b[i][j]) up[j]=0; else up[j]++; if(!b[i][j]) tp=0,S[0]=j,now=0; else { while(tp&&up[S[tp]]>=up[j]) now-=ll(up[S[tp]])*(S[tp]-S[tp-1]),tp--; S[++tp]=j; now+=ll(up[j])*(S[tp]-S[tp-1]); now%=mod; re=(re+now*(1<<k))%mod; } } } } return re%mod; } int main() { scanf("%d",&n); ll tot=0; int i,j; for(i=1;i<=n;i++) for(j=1;j<=n;j++) { scanf("%d",&a[i][j]); tot=(tot+i*j); } tot%=mod; ll ans1=work(); for(i=1;i<=n;i++)for(j=1;j<=n;j++)a[i][j]^=mask; ll ans2=work(); ans2=(tot*mask%mod-ans2)%mod; printf("%lld %lld\n",(ans1+mod)%mod,(ans2+mod)%mod); }
https://loj.ac/problem/3084code
分析:排序
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; #define N 55 ll mi[N],C[N][N]; int a[N],b[N]; inline void upd(ll &x,ll y) {x=x>y?x:y;} int trans(char *w) { if(strlen(w+1)==2) { int i; if(w[2]=='m') i=1; else if(w[2]=='p') i=2; else i=3; return (i-1)*9+w[1]-'0'; }else { if(w[1]=='E') return 28; if(w[1]=='S') return 29; if(w[1]=='W') return 30; if(w[1]=='N') return 31; if(w[1]=='Z') return 32; if(w[1]=='B') return 33; if(w[1]=='F') return 34; } return -1; } ll ch(int x,int v) { return C[a[x]][v]*mi[b[x]*v]; } ll f[35][3][3][5][2]; ll wk1() { memset(f,0,sizeof(f)); f[0][0][0][0][0]=1; int i,j,k,x,y,z,w; for(i=0;i<35;i++) { for(j=0;j<3;j++) if(!j||(i<=27&&i%9!=0&&i%9!=1)) { for(k=0;k<3;k++) if(!k||(i<=27&&i%9!=8&&i%9!=0)) if(a[i+1]>=j+k) { for(x=j+k;x<=4;x++) { for(y=0;y<2;y++) if(f[i][j][k][x][y]) { for(z=0;z<=2&&j+k+z<=a[i+1]&&x+z<=4;z++) { for(w=0;j+k+z+w*3<=a[i+1]&&x+z+w<=4;w++) { int t=j+k+z+w*3; upd(f[i+1][k][z][x+z+w][y],f[i][j][k][x][y]*ch(i+1,t)); if(!y&&t+2<=a[i+1]) upd(f[i+1][k][z][x+z+w][1],f[i][j][k][x][y]*ch(i+1,t+2)); } } if(a[i+1]-j-k==4&&x<4) upd(f[i+1][k][0][x+1][y],f[i][j][k][x][y]*ch(i+1,4)); } } } } }return f[34][0][0][4][1]; } ll c[N]; ll wk2() { int i; for(i=1;i<=34;i++)c[i]=ch(i,2); sort(c+1,c+35);ll re=1; for(i=28;i<=34;i++)re*=c[i];return re*7; } int d[20]={0,1,9,10,18,19,27,28,29,30,31,32,33,34}; ll wk3() { ll re=0;int i,j; for(i=1;i<=13;i++) { ll tmp=ch(d[i],2);for(j=1;j<=13;j++)if(i!=j)tmp*=ch(d[j],1);re=max(re,tmp); }return re*13; } void solve() { int i,j; for(i=1;i<=34;i++) a[i]=4,b[i]=0; for(mi[0]=i=1;i<=18;i++) mi[i]=mi[i-1]<<1;; for(i=0;i<=4;i++)for(C[i][0]=j=1;j<=i;j++)C[i][j]=C[i-1][j]+C[i-1][j-1]; while(1) { char w[10]; scanf("%s",w+1); if(w[1]=='0') break; a[trans(w)]--; } while(1) { char w[10]; scanf("%s",w+1); if(w[1]=='0') break; b[trans(w)]=1; } printf("%lld\n",max(wk1(),max(wk2(),wk3()))); } int main() { int T; scanf("%d",&T); while(T--) solve(); }
分析:element
#include <cstdio> #include <cstring> #include <algorithm> #include <set> #include <cmath> using namespace std; typedef long long ll; typedef double f2; #define N 500050 const f2 eps = 1e-10; int n,Y0[N],Y1[N],st,ed,is[N],tot,id[N],to[N],K,vis[N]; ll A,B,C; char buf[100000],*p1,*p2; #define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++) int rd() { int x=0; char s=nc(); while(s<'0') s=nc(); while(s>='0') x=(((x<<2)+x)<<1)+s-'0',s=nc(); return x; } set<pair<int,int> >S; set<pair<int,int> >::iterator it; f2 mn[N][2],mx[N][2]; int flg[N],wh,ch[N][2],ok[N]; struct Point { f2 p[2]; Point() {} Point(f2 x_,f2 y_) {p[0]=x_,p[1]=y_;} bool operator < (const Point &u) const { return p[wh]==u.p[wh]?p[!wh]<u.p[!wh]:p[wh]<u.p[wh]; } }a[N]; bool cmp(int x,int y) { return Y1[x]<Y1[y]; } f2 Abs(f2 x) {return x>0?x:-x;} void pushup(int p,int x) { mn[p][0]=min(mn[p][0],mn[x][0]); mn[p][1]=min(mn[p][1],mn[x][1]); mx[p][0]=max(mx[p][0],mx[x][0]); mx[p][1]=max(mx[p][1],mx[x][1]); } int build(int l,int r,int f,int k) { if(l>r) return 0; int mid=(l+r)>>1; wh=k; nth_element(a+l,a+mid,a+r+1); int p=mid; mn[p][0]=mx[p][0]=a[p].p[0]; mn[p][1]=mx[p][1]=a[p].p[1]; if(l<mid) ch[p][0]=build(l,mid-1,p,!k),pushup(p,ch[p][0]); if(r>mid) ch[p][1]=build(mid+1,r,p,!k),pushup(p,ch[p][1]); return p; } void update(int x,int y,int z,int p) { if(!p||flg[p]||x+z<mn[p][0]||x-z>mx[p][0]||y+z<mn[p][1]||y-z>mx[p][1]) return ; //if(!p) return ; if(max(max(max(abs(x-mn[p][0]),abs(x-mx[p][0])),abs(y-mn[p][1])),abs(y-mx[p][1]))-eps<z) { flg[p]=1; return ; } if(!ok[p]&&max(abs(a[p].p[0]-x),abs(a[p].p[1]-y))-eps<z) { ok[p]=1; } update(x,y,z,ch[p][0]); update(x,y,z,ch[p][1]); } int dfs(int p) { if(flg[p]) { ok[p]=1; ok[ch[p][0]]=ok[ch[p][1]]=flg[ch[p][0]]=flg[ch[p][1]]=1; } int re=ok[p]; if(ch[p][0]) re+=dfs(ch[p][0]); if(ch[p][1]) re+=dfs(ch[p][1]); return re; } int main() { scanf("%d%lld%lld%lld%d%d",&n,&A,&B,&C,&st,&ed); int i,j; for(i=1;i<=n;i++) Y0[i]=rd(); for(i=1;i<=n;i++) Y1[i]=rd(); for(i=n;i;i--) { for(it=S.begin();it!=S.end()&&(it->first < Y1[i]);it++) { j=it->second; f2 t=f2(Y0[j]-Y0[i])/(Y1[i]-Y1[j]); f2 x=(t*ed+st)/(t+1); f2 y=(t*Y1[j]+Y0[j])/(t+1); f2 tx=x,ty=y; x=tx+ty; y=tx-ty; a[++tot]=Point(x,y); } S.insert(make_pair(Y1[i],i)); } int rt=build(1,tot,0,0); K=rd(); for(i=1;i<=K;i++) { int x,y,z; x=rd(),y=rd(),z=rd(); int tx=x,ty=y; x=tx+ty; y=tx-ty; update(x,y,z,rt); } ll ans=dfs(rt)*C; ll ans1=ans+tot*A,ans2=ans+tot*A; for(i=1;i<=n;i++) id[i]=i; sort(id+1,id+n+1,cmp); ll u=n; for(i=1;i<=n;i++) if(!vis[i]) { u--; for(j=i;!vis[j];j=id[j]) vis[j]=1; } ans2+=(tot-u)*(B-A); if(ans1>ans2) swap(ans1,ans2); printf("%lld %lld\n",ans1,ans2); }
https://loj.ac/problem/3086get
分析:string
#include <cstdio> #include <cstring> #include <algorithm> #include <cstdlib> #include <queue> using namespace std; #define N 1000050 #define mod 1000000007 typedef long long ll; struct Mat { ll a[6][6]; Mat() {memset(a,0,sizeof(a));} Mat operator * (const Mat &u) const { Mat re; int i,j,k; for(i=0;i<6;i++)for(k=0;k<6;k++)for(j=0;j<6;j++) { re.a[i][j]+=a[i][k]*u.a[k][j]; } for(i=0;i<6;i++)for(j=0;j<6;j++)re.a[i][j]%=mod; return re; } }G[33]; Mat qp(Mat x,int y) { Mat I; int i; for(i=0;i<6;i++) I.a[i][i]=1; for(i=0;i<=30;i++) if(y&(1<<i)) I=I*G[i]; return I; } int main() { int i; Mat x; int t; x.a[0][0]=x.a[0][1]=x.a[1][0]=x.a[2][0]=x.a[2][1]=x.a[2][3]=1; x.a[3][2]=x.a[4][4]=x.a[4][5]=x.a[5][4]=1; x.a[4][3]=2; G[0]=x; for(i=1;i<=30;i++) G[i]=G[i-1]*G[i-1]; scanf("%d",&t); while(t--) { int y;scanf("%d",&y); if(y<=2) {puts("0"); continue;} Mat t=qp(x,y-1); ll ans=(t.a[4][0]+t.a[4][1]+t.a[4][2]); printf("%lld\n",ans%mod); } }
題意:有向圖,給K個點,求兩兩之間最短的最短路。
分析:
#include <cstdio> #include <cstring> #include <algorithm> #include <cstdlib> #include <queue> using namespace std; #define N 100050 #define M 600050 char buf[100000],*p1,*p2; #define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++) int rd() { int x=0; char s=nc(); while(s<'0') s=nc(); while(s>='0') x=(((x<<2)+x)<<1)+s-'0',s=nc(); return x; } typedef long long ll; int head[N],to[M],nxt[M],val[M],vis[N],n,cnt,S,m,K,a[N]; ll dis[N]; priority_queue<pair<ll,int> >q; inline void add(int u,int v,int w) { to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt; val[cnt]=w; } void dij() { int i; memset(dis+1,0x3f,S<<3); memset(vis+1,0,S<<2); dis[S]=0; q.push(make_pair(0,S)); while(!q.empty()) { int x=q.top().second; q.pop(); if(vis[x]) continue; vis[x]=1; for(i=head[x];i;i=nxt[i]) if(dis[to[i]]>dis[x]+val[i]) { dis[to[i]]=dis[x]+val[i]; q.push(make_pair(-dis[to[i]],to[i])); } } } void solve() { n=rd(),m=rd(),K=rd(); int i,x,y,z,j; S=n+1; memset(head+1,0,S<<2); cnt=0; for(i=1;i<=m;i++) { x=rd(),y=rd(),z=rd(); add(x,y,z); } for(i=1;i<=K;i++) a[i]=rd(); random_shuffle(a+1,a+K+1); random_shuffle(a+1,a+K+1); random_shuffle(a+1,a+K+1); int tmp=cnt; ll ans=1ll<<60; for(i=0;i<5;i++) { cnt=tmp; for(j=1;j<=K;j++) if((j>>i)&1) add(S,a[j],0); dij(); for(j=1;j<=K;j++) if(!((j>>i)&1)) ans=min(ans,dis[a[j]]); head[S]=0; cnt=tmp; for(j=1;j<=K;j++) if(!((j>>i)&1)) add(S,a[j],0); dij(); for(j=1;j<=K;j++) if((j>>i)&1) ans=min(ans,dis[a[j]]); head[S]=0; } printf("%lld\n",ans); } int main() { int T; scanf("%d",&T); while(T--)solve(); }
題意:
一棵樹,每次給出\(x,y\),求\(\sum\limits_{i\le x}\mathrm{dep(lca(i,y))^k}\)
分析:
#include <cstdio> #include <cstring> #include <algorithm> #include <cstdlib> #include <queue> using namespace std; #define N 50050 #define ls p<<1 #define rs p<<1|1 #define mod 998244353 char buf[100000],*p1,*p2; #define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++) int rd() { int x=0; char s=nc(); while(s<'0') s=nc(); while(s>='0') x=(((x<<2)+x)<<1)+s-'0',s=nc(); return x; } typedef long long ll; int head[N],to[N],nxt[N],fa[N],top[N],dep[N],siz[N],son[N],dfn[N],idf[N],cnt; int n,Q,K; ll h[N],w[N],sum[N<<2],tag[N<<2],sv[N<<2],ans[N]; struct A { int x,y,id; bool operator < (const A &u) const { return x<u.x; } }q[N]; ll qp(ll x,ll y) { ll re=1;for(;y;y>>=1,x=x*x%mod)if(y&1)re=re*x%mod;return re; } inline void add(int u,int v) { to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt; } void d1(int x) { int i;siz[x]=1; for(i=head[x];i;i=nxt[i]) { dep[to[i]]=dep[x]+1; d1(to[i]);siz[x]+=siz[to[i]]; if(siz[to[i]]>siz[son[x]]) son[x]=to[i]; } } void d2(int x,int t) { top[x]=t; int i; dfn[x]=++dfn[0]; idf[dfn[0]]=x; if(son[x]) d2(son[x],t); for(i=head[x];i;i=nxt[i]) if(to[i]!=son[x]) d2(to[i],to[i]); } void build(int l,int r,int p) { if(l==r) {sv[p]=w[idf[l]]; return ;} int mid=(l+r)>>1; build(l,mid,ls),build(mid+1,r,rs); sv[p]=(sv[ls]+sv[rs])%mod; } inline void giv(int p,ll d) { sum[p]=(sum[p]+d*sv[p])%mod; tag[p]+=d; } inline void pushdown(int p) { if(tag[p]) { giv(ls,tag[p]),giv(rs,tag[p]); tag[p]=0; } } void update(int l,int r,int x,int y,int p) { if(x<=l&&y>=r) {giv(p,1); return ;} int mid=(l+r)>>1; pushdown(p); if(x<=mid) update(l,mid,x,y,ls); if(y>mid) update(mid+1,r,x,y,rs); sum[p]=(sum[ls]+sum[rs])%mod; } ll query(int l,int r,int x,int y,int p) { if(x<=l&&y>=r) return sum[p]; int mid=(l+r)>>1; ll re=0; pushdown(p); if(x<=mid) re=query(l,mid,x,y,ls); if(y>mid) re=(re+query(mid+1,r,x,y,rs))%mod; return re; } void fix(int x) { for(;top[x]!=1;x=fa[top[x]]) { update(1,n,dfn[top[x]],dfn[x],1); } update(1,n,1,dfn[x],1); } ll ask(int x) { ll re=0; for(;top[x]!=1;x=fa[top[x]]) { re+=query(1,n,dfn[top[x]],dfn[x],1); }re+=query(1,n,1,dfn[x],1); return re%mod; } int main() { n=rd(),Q=rd(),K=rd(); int i; for(i=2;i<=n;i++) fa[i]=rd(),add(fa[i],i); dep[1]=1,d1(1),d2(1,1); for(i=1;i<=n;i++) h[i]=qp(i,K); for(i=n;i;i--) h[i]=h[i]-h[i-1]; for(i=1;i<=n;i++) w[i]=(h[dep[i]]+mod)%mod; build(1,n,1); for(i=1;i<=Q;i++) { q[i].x=rd(),q[i].y=rd(); q[i].id=i; } sort(q+1,q+Q+1); int j=1; for(i=1;i<=Q;i++) { for(;j<=n&&j<=q[i].x;j++) { fix(j); } ans[q[i].id]=ask(q[i].y); } for(i=1;i<=Q;i++) printf("%lld\n",(ans[i]+mod)%mod); }
總結:一場難度低於\(\mathrm{noip}\)的省選,\(d1t3\)的置換部分仍是不錯的。