2021 icpc 南京游记
打铜了
爬了
补题:
$I$
一道终极歪榜题
路线事实上一共有$2H$种,可以映射到$[-H,H)$上,$\ge 0 $的部分表示$x=0$时向上
用$map$简单维护一下即可
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 #define inf 2139062143 3 #define ll long long 4 #define db double 5 #define ld long double 6 #define ull unsigned long long 7 #define MAXN 100100 8 #define MOD 998244353 9 #define Fill(a,x) memset(a,x,sizeof(a)) 10 #define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i) 11 #define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i) 12 #define ren for(int i=fst[x];i;i=nxt[i]) 13 #define pii pair<int,int> 14 #define vi vector<int> 15 #define fi first 16 #define se second 17 #define pb push_back 18 using namespace std; 19 inline int read() 20 { 21 int x=0,f=1;char ch=getchar(); 22 while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} 23 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 24 return x*f; 25 } 26 namespace CALC 27 { 28 inline int pls(int a,int b){return a+b>=MOD?a+b-MOD:(a+b<0?a+b+MOD:a+b);} 29 inline int mns(int a,int b){return a-b<0?a-b+MOD:(a-b>=MOD?a-b-MOD:a-b);} 30 inline int mul(int a,int b){return (1LL*a*b)%MOD;} 31 inline void inc(int &a,int b){a=pls(a,b);} 32 inline void dec(int &a,int b){a=mns(a,b);} 33 inline void tms(int &a,int b){a=mul(a,b);} 34 inline int qp(int x,int t,int res=1) 35 {for(;t;t>>=1,x=mul(x,x)) if(t&1) res=mul(res,x);return res;} 36 inline int Inv(int x){return qp(x,MOD-2);} 37 } 38 using namespace CALC; 39 int H,n,m,ans; 40 pii g[MAXN<<1]; 41 map<int,int> res; 42 int main() 43 { 44 rep(T,1,read()) 45 { 46 ans=0;res.clear();res[0]=0; 47 H=read();n=read();int x,y,ya,yb,tmp; 48 rep(i,1,n) g[i].fi=read(),g[i].se=read(); 49 m=read();rep(i,1,m) g[i+n].fi=read(),g[i+n].se=0-read(); 50 sort(g+1,g+n+m+1); 51 rep(i,1,n+m) 52 { 53 x=g[i].fi,y=abs(g[i].se); 54 x%=2*H;if(x>=H) y=H-y,x-=H; 55 ya=y-x,yb=y+x<=H?-y-x:2*H-y-x; 56 if(g[i].se>0&&(res.count(ya)||res.count(yb))) 57 tmp=max(res[ya],res[yb]),res[ya]=res[yb]=tmp; 58 else if(g[i].se<0) 59 { 60 if(res.count(ya)) res[ya]++,ans=max(ans,res[ya]); 61 if(res.count(yb)) res[yb]++,ans=max(ans,res[yb]); 62 } 63 } 64 printf("%d\n",ans); 65 } 66 }
$J$
搜索题
每次枚举两个数之差$d$的质因数$p$,则这一次的最优操作一定是通过加减得到上/下取整
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 #define inf 2139062143 3 #define ll long long 4 #define db double 5 #define ld long double 6 #define ull unsigned long long 7 #define MAXN 100100 8 #define MOD 998244353 9 #define Fill(a,x) memset(a,x,sizeof(a)) 10 #define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i) 11 #define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i) 12 #define ren for(int i=fst[x];i;i=nxt[i]) 13 #define pii pair<int,int> 14 #define vi vector<int> 15 #define fi first 16 #define se second 17 #define pb push_back 18 using namespace std; 19 inline int read() 20 { 21 int x=0,f=1;char ch=getchar(); 22 while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} 23 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 24 return x*f; 25 } 26 namespace CALC 27 { 28 inline int pls(int a,int b){return a+b>=MOD?a+b-MOD:(a+b<0?a+b+MOD:a+b);} 29 inline int mns(int a,int b){return a-b<0?a-b+MOD:(a-b>=MOD?a-b-MOD:a-b);} 30 inline int mul(int a,int b){return (1LL*a*b)%MOD;} 31 inline void inc(int &a,int b){a=pls(a,b);} 32 inline void dec(int &a,int b){a=mns(a,b);} 33 inline void tms(int &a,int b){a=mul(a,b);} 34 inline int qp(int x,int t,int res=1) 35 {for(;t;t>>=1,x=mul(x,x)) if(t&1) res=mul(res,x);return res;} 36 inline int Inv(int x){return qp(x,MOD-2);} 37 } 38 using namespace CALC; 39 int p[MAXN],ntp[MAXN],tot; 40 map<pii,int> m; 41 void init(int n) 42 { 43 rep(i,2,n) 44 { 45 if(!ntp[i]) p[++tot]=i; 46 rep(j,1,tot) if(p[j]*i>n) break; 47 else{ntp[i*p[j]]=1;if(i%p[j]==0) break;} 48 } 49 } 50 int dfs(int x,int d) 51 { 52 //cout<<x<<" "<<d<<endl; 53 if(x==1) return 0; 54 if(d==1) return x-1; 55 if(m.count({x,d})) return m[{x,d}]; 56 int res=x-1,pi,now=d; 57 rep(i,1,tot) if(p[i]*p[i]>now) break; 58 else if(now%p[i]==0) 59 { 60 pi=p[i]; 61 if(x%pi==0) res=min(res,dfs(x/pi,d/pi)+1); 62 else 63 { 64 if(x>=pi) res=min(res,dfs(x/pi,d/pi)+1+x%pi); 65 res=min(res,dfs((x+pi-1)/pi,d/pi)+1+pi-x%pi); 66 } 67 while(now%p[i]==0) now/=p[i]; 68 } 69 if(now>100000||(now>1&&!ntp[now])) 70 { 71 pi=now; 72 if(x%pi==0) res=min(res,dfs(x/pi,d/pi)+1); 73 else 74 { 75 if(x>=pi) res=min(res,dfs(x/pi,d/pi)+1+x%pi); 76 res=min(res,dfs((x+pi-1)/pi,d/pi)+1+pi-x%pi); 77 } 78 } 79 return m[{x,d}]=res; 80 } 81 int main() 82 { 83 init(1e5); 84 rep(T,1,read()) 85 { 86 int a=read(),b=read(); 87 if(a>b) swap(a,b); 88 printf("%d\n",dfs(a,b-a)); 89 } 90 }
$E$
照着官方题解写的:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 #define ll long long 3 #define inf 2139062143 4 #define MAXN 100100 5 #define MOD 1000000007 6 #define pii pair<int,int> 7 #define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i) 8 #define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i) 9 #define pb push_back 10 using namespace std; 11 inline int read() 12 { 13 int x=0,f=1;char ch=getchar(); 14 while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} 15 while(isdigit(ch)) x=x*10+ch-'0',ch=getchar(); 16 return x*f; 17 } 18 inline int pls(int a,int b){return a+b>=MOD?a+b-MOD:a+b;} 19 inline int mns(int a,int b){return a-b<0?a-b+MOD:a-b;} 20 inline int mul(int a,int b){return 1LL*a*b%MOD;} 21 inline int sqr(int x){return mul(x,x);} 22 inline void inc(int &a,int b){a=pls(a,b);} 23 inline void dec(int &a,int b){a=mns(a,b);} 24 inline void tms(int &a,int b){a=mul(a,b);} 25 struct mat 26 { 27 int a[6]; 28 void mem(){memset(a,0,sizeof(a));} 29 void getw(int w){a[0]=w;a[1]=a[2]=sqr(w),a[3]=a[4]=mul(2,w),a[5]=1;} 30 mat operator * (const mat &x) 31 { 32 mat res; 33 res.a[0]=pls(a[0],x.a[0]); 34 res.a[1]=pls(pls(x.a[1],a[1]),mul(a[0],x.a[3])); 35 res.a[2]=pls(x.a[2],a[2]); 36 inc(res.a[2],pls(mul(a[0],x.a[4]),mul(a[1],x.a[5]))); 37 res.a[3]=pls(a[3],x.a[3]); 38 res.a[4]=pls(pls(x.a[4],a[4]),mul(a[3],x.a[5])); 39 res.a[5]=pls(a[5],x.a[5]); 40 return res; 41 } 42 bool operator == (const mat &x) 43 { 44 rep(i,0,5) if(a[i]!=x.a[i]) return 0; 45 return 1; 46 } 47 }tag[MAXN<<2],zr; 48 struct vec 49 { 50 int a[4]; 51 vec operator + (const vec &x) 52 { 53 vec res;rep(i,0,3) res.a[i]=pls(a[i],x.a[i]); 54 return res; 55 } 56 vec operator * (const mat &x) 57 { 58 vec res; 59 res.a[0]=a[0]; 60 res.a[1]=pls(mul(x.a[0],a[0]),a[1]); 61 res.a[2]=pls(pls(mul(x.a[1],a[0]),mul(x.a[3],a[1])),a[2]); 62 res.a[3]=pls(pls(mul(x.a[2],a[0]),mul(x.a[4],a[1])),pls(mul(x.a[5],a[2]),a[3])); 63 return res; 64 } 65 }tr[MAXN<<2]; 66 int n,m,Q,h[MAXN],res[MAXN]; 67 struct Ask{int x,l,r,w,id;}q[MAXN]; 68 struct Data{int l,r,w;}g[MAXN]; 69 bool operator < (const Ask &a,const Ask &b){return a.x<b.x;} 70 inline void upd(int k){tr[k]=tr[k<<1]+tr[k<<1|1];} 71 void build(int k,int l,int r) 72 { 73 if(l==r) {tr[k]={1,h[l],sqr(h[l]),sqr(h[l])};return ;} 74 int mid=l+r>>1;build(k<<1,l,mid);build(k<<1|1,mid+1,r); 75 upd(k); 76 } 77 inline void Mdf(int k,mat w){tr[k]=tr[k]*w,tag[k]=tag[k]*w;} 78 void pshd(int k) 79 { 80 if(tag[k]==zr) return ; 81 Mdf(k<<1,tag[k]);Mdf(k<<1|1,tag[k]);tag[k].mem(); 82 } 83 int query(int k,int l,int r,int a,int b) 84 { 85 if(a<=l&&r<=b) return tr[k].a[3]; 86 int mid=l+r>>1,res=0;pshd(k); 87 if(a<=mid) inc(res,query(k<<1,l,mid,a,b)); 88 if(b>mid) inc(res,query(k<<1|1,mid+1,r,a,b)); 89 return res; 90 } 91 void mdf(int k,int l,int r,int a,int b,mat w) 92 { 93 if(a<=l&&r<=b){Mdf(k,w);return ;} 94 int mid=l+r>>1;pshd(k); 95 if(a<=mid) mdf(k<<1,l,mid,a,b,w); 96 if(b>mid) mdf(k<<1|1,mid+1,r,a,b,w); 97 upd(k); 98 } 99 int main() 100 { 101 n=read(),m=read(),Q=read();rep(i,1,n) h[i]=pls(read(),MOD); 102 build(1,1,n);int a,b,c,d; 103 zr.mem();mat tmp; 104 rep(i,1,m) g[i].l=read(),g[i].r=read(),g[i].w=pls(read(),MOD); 105 rep(i,0,Q-1) a=read(),b=read(),c=read(),d=read(),q[i*2+1]={c-1,a,b,-1,i+1},q[i*2+2]={d,a,b,1,i+1}; 106 Q<<=1;sort(q+1,q+Q+1);int pos=1; 107 while(q[pos].x==-1) pos++; 108 rep(i,0,m) 109 { 110 if(i) 111 { 112 tmp.getw(g[i].w); 113 mdf(1,1,n,g[i].l,g[i].r,tmp); 114 tmp.getw(0); 115 if(g[i].l>1) mdf(1,1,n,1,g[i].l-1,tmp); 116 if(g[i].r<n) mdf(1,1,n,g[i].r+1,n,tmp); 117 } 118 while(pos<=Q&&q[pos].x<=i) 119 { 120 if(q[pos].w==1) inc(res[q[pos].id],query(1,1,n,q[pos].l,q[pos].r)); 121 else dec(res[q[pos].id],query(1,1,n,q[pos].l,q[pos].r)); 122 pos++; 123 } 124 } 125 rep(i,1,Q>>1) printf("%d\n",res[i]); 126 }
$G$
使用题解中所述的dp,实际中可以通过一个操作把题解中的mask状态省去
即每一个点再向外额外连一个点,这样当$dp(u,v,t)$中$u,v$有额外节点时,即代表了这一段不可扩展
因此在新的树中,$dp(u,v,t)$表示$u~v$路径上不算最外面两条边的答案
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 #define ll long long 3 #define MAXN 100100 4 #define pii pair<int,int> 5 #define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i) 6 #define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i) 7 #define ren for(int i=fst[x];i;i=nxt[i]) 8 #define pb push_back 9 using namespace std; 10 inline int read() 11 { 12 int x=0,f=1;char ch=getchar(); 13 while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} 14 while(isdigit(ch)) x=x*10+ch-'0',ch=getchar(); 15 return x*f; 16 } 17 const ll inf=1e18; 18 int n,val[310]; 19 vector<int> G[310]; 20 int fa[310][310],sz[310][310]; 21 ll f[155][310][310]; 22 void dfs(int x,int pa,const int& anc) 23 { 24 fa[anc][x]=pa,sz[anc][x]=(x<=n); 25 for(auto v:G[x]) if(v^pa) 26 dfs(v,x,anc),sz[anc][x]+=sz[anc][v]; 27 } 28 void solve() 29 { 30 n=read()+1;int a,b; 31 rep(i,1,n-1) val[i]=read(); 32 rep(i,1,n-1) a=read(),b=read(),G[a].pb(b),G[b].pb(a); 33 rep(i,1,n) G[i].pb(i+n),G[i+n].pb(i); 34 rep(i,1,n<<1) dfs(i,0,i); 35 rep(t,0,n-1) rep(i,1,n<<1) rep(j,1,n<<1) f[t][i][j]=-inf; 36 rep(x,1,n) rep(i,0,G[x].size()-1) rep(j,i+1,G[x].size()-1) 37 f[0][G[x][i]][G[x][j]]=f[0][G[x][j]][G[x][i]]=0; 38 rep(t,0,n-2) rep(i,1,n<<1) rep(j,i+1,n<<1) if(f[t][i][j]>=0) 39 { 40 //cout<<t<<" "<<i<<" "<<j<<" "<<f[t][i][j]<<endl; 41 if(n-1-sz[i][j]-sz[j][i]>=t+1) 42 f[t+1][i][j]=f[t+1][j][i]=max(f[t+1][i][j],f[t][i][j]); 43 for(auto v:G[i]) if(v^fa[j][i]) 44 f[t+1][j][v]=f[t+1][v][j]=max(f[t+1][j][v],f[t][i][j]+val[t+1]); 45 for(auto v:G[j]) if(v^fa[i][j]) 46 f[t+1][i][v]=f[t+1][v][i]=max(f[t+1][i][v],f[t][i][j]+val[t+1]); 47 } 48 ll ans=0; 49 rep(i,1,n<<1) rep(j,i+1,n<<1) ans=max(ans,f[n-1][i][j]); 50 printf("%lld\n",ans); 51 rep(i,1,n<<1) G[i].clear(); 52 } 53 int main() 54 { 55 rep(T,1,read()) solve(); 56 }