CQOI 2020 nothing to remember

Joint provincial elections are really boringDay0Day0Day0 Reviewed a lot of knowledge points that Day1Day2Day1Day2Day1Day...

Joint provincial elections are really boring
Day0Day0Day0
Reviewed a lot of knowledge points that Day1Day2Day1Day2Day1Day2 didn't take the exam.
Day1Day1Day1

T1. Ice Fire Warrior

It is enough to bisect on the line tree.
After finishing writing, I found that it was the highest temperature, which forced me to write another line tree dichotomy. I found that I was too lazy to run for 6s, and I came out to find that I still ran very fast
Code\mathcal CodeCode

#include<bits/stdc++.h> #define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++) #define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--) #define LL long long #define pb push_back #define mp make_pair #define Ct const #define db double #define maxn 2000006 using namespace std; char cb[1<<16],*cs=cb,*ct=cb; #define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<16,stdin),cs==ct)?0:*cs++) void read(int &res){ char ch;bool f=0; for(;!isdigit(ch=getc());) if(ch == '-') f = 1; for(res=ch-'0';isdigit(ch=getc());res=res*10+ch-'0'); (f) && (res = -res); } int n; int sb[maxn],sm[maxn<<2][2],pv[maxn][2],smh; int data[maxn][4]; int sml , smr , pt; #define lc u<<1 #define rc lc|1 void ins(int u,int l,int r,int p,int t,int v){ sm[u][t] += v; if(l==r) return; int m = l+r>>1; p <= m ? ins(lc,l,m,p,t,v) : ins(rc,m+1,r,p,t,v); } void qry(int u,int l,int r,int v){ if(l == r){ pt = l; return; } int m = l+r>>1; if(v + sm[lc][0] + sm[lc][1] - pv[m][1] >= 0) qry(lc,l,m,v); else smr -= sm[lc][1] , sml += sm[lc][0] , qry(rc,m+1,r,v + sm[lc][0] + sm[lc][1]); } int qry2(int u,int l,int r,int v){ if(l == r) return l; int m = l+r>>1; if(v - sm[rc][1] > 0) return qry2(lc,l,m,v-sm[rc][1]); return qry2(rc,m+1,r,v); } void print(int a){ static int q[20]={}; for(;a;a/=10) q[++q[0]] = a % 10; if(!q[0]) putchar('0'); for(;q[0];) putchar('0' + q[q[0] --]); } int main(){ read(n); rep(i,1,n){ read(data[i][0]) , read(data[i][1]); if(data[i][0] == 1) read(data[i][2]) , read(data[i][3]) , sb[++sb[0]] = data[i][2]; } sort(sb+1,sb+1+sb[0]); sb[0] = unique(sb+1,sb+1+sb[0]) - sb - 1; rep(i,1,n){ if(data[i][0] == 1){ int v = data[i][2] = lower_bound(sb+1,sb+1+sb[0],data[i][2])-sb , t = data[i][1]; pv[v][t] += data[i][3]; if(t) smh += data[i][3]; ins(1,1,sb[0],v,t,data[i][3]); } else{ int u = data[i][1] , v = data[u][2] , t = data[u][1]; pv[v][t] -= data[u][3]; if(t) smh -= data[u][3]; ins(1,1,sb[0],v,t,-data[u][3]); } sml = 0 , smr = smh; qry(1,1,sb[0],-smh); int ans =max(smr,sml); if(!ans) puts("Peace"); else{ if(ans == smr){ print(sb[qry2(1,1,sb[0],smr)]); } else print(sb[pt-1]); putchar(' '); print(ans << 1); putchar('\n'); } } }

T2 combination number problem

I wrote a junk log in the exam room
∑k=0nki‾xk(nk)=xid∑k=0nxk(nk)dx=xini‾(1+x)n−i\sum_^n k^{\underline }x^k\binom nk = x^i\frac {{\rm d}\sum_^n x^k\binom nk}{{\rm d}x} = x^i n^{\underline i}(1+x)^k=0∑n​ki​xk(kn​)=xidxd∑k=0n​xk(kn​)​=xini​(1+x)n−i
So we only need to set f(k) = ∑ i=0maikif(k) = \sum_^m a_ik^if(k)=∑i=0m​ai​ki
Convert to lower power polynomial f (k) = ∑ i=0mciki ‾ f(k) = \sum_^m c_ik^{\underline i}f(k)=∑i=0m​ci​ki​
It can be solved by O (M log ⁡ n)O(m\log n)O(mlogn).
The transformation can be realized without division O(m2)O(m^2)O(m2) by Stirling number.
I don't know why I need to divide factorials.
AC Code\mathcal AC \ CodeAC Code

#include<bits/stdc++.h> #define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++) #define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--) #define LL long long #define pb push_back #define mp make_pair #define Ct const #define pii pair<int,int> #define db double #define maxn 1005 using namespace std; char cb[1<<16],*cs=cb,*ct=cb; #define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<16,stdin),cs==ct)?0:*cs++) void read(int &res){ char ch;bool f=0; for(;!isdigit(ch=getc());) if(ch == '-') f = 1; for(res=ch-'0';isdigit(ch=getc());res=res*10+ch-'0'); (f) && (res = -res); } int n,x,p,m,a[maxn],C[maxn][maxn],b[maxn],c[maxn]; int Pow(int b,int k,int mod){ int r=1;for(;k;k>>=1,b=1ll*b*b%mod) if(k&1) r=1ll*r*b%mod; return r; } void exgcd(int a,int b,int &x,int &y,int &gcd){ if(!b) x = 1 , y = 0 , gcd = a; else exgcd(b,a%b,y,x,gcd), y-=(a/b)*x; } int INV(int x,int md){ int a,b,c; exgcd(x,md,a,b,c); return a; } int Solve(int p,int md){ rep(i,C[0][0]=1,m) rep(j,C[i][0]=1,i) C[i][j] = (C[i-1][j-1] + C[i-1][j]) % md; rep(i,0,m){ c[i] = 0; per(j,m,0) c[i] = (1ll * c[i] * i + a[j]) % md; } rep(i,0,m){ b[i] = 0; rep(j,0,i) b[i] = (b[i] + (i-j&1 ? -1ll : 1ll) * C[i][j] * c[j]) % md; } int rs=1,pw=0,ret=0; rep(i,0,m){ int cc = 1ll * rs * Pow(p,pw,md) % md; ret = (ret + 1ll * Pow(x , i,md) * Pow(1+x,n-i,md) % md * b[i] % md * cc) % md; int v = n - i; for(;v && v % p == 0; v/= p) pw++; rs = 1ll * rs * v % md; v = i+1; for(;v && v % p == 0;v /= p) pw--; rs = 1ll * rs * INV(v,md) % md; } return ret; } int main(){ read(n),read(x),read(p),read(m); rep(i,0,m) read(a[i]); int X = p; int ans = 0 , md = 1; for(int i=2;i*i<=X;i++) if(X % i == 0){ int pw = 1; for(;X % i == 0;X /= i) pw *= i; int ret = Solve(i,pw); int x,y,gd; exgcd(md,pw,x,y,gd); x = 1ll * x * ((ret - ans) / gd) % (md * pw); ans = (1ll * x * md + ans) % (md * pw); md *= pw; } if(X > 1){ int pw = X; int ret = Solve(X,pw); int x,y,gd; exgcd(md,pw,x,y,gd); x = 1ll * x * ((ret - ans) / gd) % (md * pw); ans = (1ll * x * md + ans) % (md * pw); md *= pw; } printf("%d\n",(ans+md)%md); }

T3: magic shop

It is found that the number of gifts of the two schemes is the same.
It's hard to guess that we only need to ensure that if one gift in AAA is replaced by another gift and still meets the conditions, then the value of the replaced scheme must be ≥ geq ≥ the original scheme, because no other gift in AAA has been replaced, so it becomes the big and small relationship between two gifts, vi ≤ vjv_i \leq v_jvi ≤ vj is connected into a digraph, and then write an L2L_ The order preserving regression of 2l2 is enough.
CodeCodeCode

#include<bits/stdc++.h> #define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++) #define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--) #define pb push_back #define mp make_pair #define Ct const #define db double #define pii pair<int,int> #define inf 0x3f3f3f3f3f3f3f3fll #define LL long long #define maxn 1005 using namespace std; int n,m,a[maxn],b[maxn],v[maxn],ina[maxn],inb[maxn]; int sz; unsigned long long c[maxn]; unsigned long long ar[100]; void ins(unsigned long long x){ for(int i=0;x && i<64;i++) if(x >> i & 1){ if(ar[i]) x ^= ar[i]; else ar[i] = x , sz++ , x = 0; } } #define maxm maxn * maxn int buf[maxn],info[maxn],Prev[maxm],to[maxm],cnt_e=1,S,T; LL cap[maxm],ans; void Node(int u,int v,LL c){ Prev[++cnt_e]=info[u],info[u]=cnt_e,to[cnt_e]=v,cap[cnt_e]=c; } void Line(int u,int v,LL c){ Node(u,v,c),Node(v,u,0); } LL sqr(LL a){ return a * a; } int h[maxn]; bool BFS(vector<int>&A){ static int q[maxn],L,R; rep(i,0,A.size()-1) info[A[i]] = buf[A[i]] , h[A[i]] = -1; info[S] = buf[S] , info[T] = buf[T]; q[L=R=0] = T;h[S] = -1 , h[T] = 0; for(int u;L<=R;){ u=q[L++]; for(int i=info[u],v;i;i=Prev[i]){ if(cap[i^1] && h[v=to[i]] == -1) h[v] = h[u] + 1, q[++R] = v; } } return h[S] != -1; } LL aug(int u,LL mx){ if(u == T) return mx; LL st = mx , inc; for(int &i=info[u],v;i;i=Prev[i]) if(cap[i] && h[v=to[i]] + 1 == h[u] && (inc = aug(v , min(cap[i] , st)))){ st -= inc , cap[i] -= inc , cap[i^1] += inc; if(!st) return mx - st; } return mx - st; } int cl[maxn]; void Solve(int L,int R,vector<int>&A,vector<pii>&E){ if(L == R){ rep(i,0,A.size()-1) ans += sqr(v[A[i]] - L); return; } if(A.empty()) return; if(A.size() == 1){ ans += sqr(max(L-v[A[0]] , max(v[A[0]]-R , 0))); return; } int mid = L+R >> 1; rep(i,0,E.size()-1) Line(E[i].first , E[i].second , inf); rep(i,0,A.size()-1) if(v[A[i]] > mid) Line(S,A[i],sqr(mid-v[A[i]])-sqr(mid+1-v[A[i]])); else Line(A[i],T,sqr(mid+1-v[A[i]])-sqr(mid-v[A[i]])); rep(i,0,A.size()-1) buf[A[i]] = info[A[i]]; buf[S] = info[S] , buf[T] = info[T]; for(;BFS(A);) aug(S,inf); vector<int>ls,rs; rep(i,0,A.size()-1) if(v[A[i]] > mid){ if(h[A[i]] == -1) rs.pb(A[i]) , cl[A[i]] = 1; else ls.pb(A[i]) , cl[A[i]] = 0; } else{ if(h[A[i]] == -1) rs.pb(A[i]) , cl[A[i]] = 1; else ls.pb(A[i]) , cl[A[i]] = 0; } vector<pair<int,int> >le,re; rep(i,0,E.size()-1) if(cl[E[i].first] == cl[E[i].second]){ if(cl[E[i].first]) re.pb(E[i]); else le.pb(E[i]); } rep(i,0,A.size()-1) info[A[i]] = 0; cnt_e = 1;info[S] = info[T] = 0; Solve(L,mid,ls,le) , Solve(mid+1,R,rs,re); } int main(){ freopen("shop.in","r",stdin); freopen("shop.out","w",stdout); scanf("%d%d",&n,&m); rep(i,1,n) cin >> c[i]; int mx = 0 , mn = 0x3f3f3f3f; rep(i,1,n) scanf("%d",&v[i]) , mx = max(mx , v[i]) , mn = min(mn , v[i]); rep(i,1,m) scanf("%d",&a[i]),ina[a[i]] = 1; rep(i,1,m) scanf("%d",&b[i]),inb[b[i]] = 1; vector<pii >E; rep(i,1,m) rep(j,1,n){ if(!ina[j]){ sz = 0; memset(ar,0,sizeof ar); rep(k,1,m) if(k!=i) ins(c[a[k]]); ins(c[j]); if(sz == m) E.pb(mp(a[i],j)); } if(!inb[j]){ sz = 0; memset(ar,0,sizeof ar); rep(k,1,m) if(k!=i) ins(c[b[k]]); ins(c[j]); if(sz == m) E.pb(mp(j,b[i])); } } S = n + 1 , T = n + 2; vector<int>p; rep(i,1,n) p.pb(i); Solve(mn,mx,p,E); cout << ans << endl; }

Hope Day1 can AK

Day2Day2Day2

T1. Signal transmission

The pressure dpdpm22mm ^ 22mm22m is obvious.
Consider the contribution of uuu to a point when it joins.
The contribution of uuu can be divided into the following parts:
Set ppp as current position, au,va_au,v is the number of times from uuu to vvv.
V v v: AV, up + Au, V (P + 1) Ka in front of uuu_ p +a_ (p+1)kav,u​p+au,v​(p+1)k
V v v: au,v(− P) + AV, u (P + 1) Ka after uuu_ (-p)+a_ (p+1)kau,v​(−p)+av,u​(p+1)k
So maintain FSTA and UF respectively_ FSTA, u denotes AV, UA with stastasta state in front of uuu_ The sum of AV, u and so on,
Then o (M2 m) O (M2 ^ m) O (M2M)
However, it is found that the space is O (M2 m) O (M2M) O (M2M).
It is found that the dpdpdp of this fff is dpdpdp on the dfsdfsdfs tree constructed on the DAGDAGDAG composed of points in 0 → 2m − 10 \rightarrow 2^m-10 → 2m − 1. We enumerate from 000 to 2m − 12^m-12m − 1, which is actually traversing a dfsdfsdfs tree. Then the transfer on the tree can only record the fff card space of each layer.
See code for specific implementation:
Code\mathcal CodeCode

#include<bits/stdc++.h> #define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++) #define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--) #define pb push_back #define LL long long #define Ct const #define db double #define mp make_pair #define maxn 23 using namespace std; char cb[1<<16],*cs=cb,*ct=cb; #define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<16,stdin),cs==ct)?0:*cs++) void read(int &res){ char ch;bool f=0; for(;!isdigit(ch=getc());) if(ch=='-') f=1; for(res=ch-'0';isdigit(ch=getc());res=res*10+ch-'0'); (f) && (res=-res); } int n,M,m,K,a[maxn][maxn],f[1<<maxn],bit[1<<maxn],lg[1<<maxn],sm[maxn]; int g[33][33] , h[33][33] , nb[33] , tp; int main(){ read(n),read(m),read(K); int pr;read(pr);pr--; rep(i,2,n){ int x;read(x);x--; if(x ^ pr){ a[pr][x]++; sm[pr]++ , sm[x] ++; } pr=x; } M = 1 << m; rep(i,0,m-1) lg[1 << i] = i; rep(i,0,M-1) bit[i] = bit[i>>1] + (i&1) , f[i] = 0x3f3f3f3f; rep(i,0,m-1) rep(j,0,m-1) if(i!=j) g[0][i] += a[i][j]; nb[tp=0] = 0; f[0] = 0; rep(i,0,M-2){ if(i){ int sta = i - (i&-i) , v = lg[i&-i] , rsta = M-i-1 , cnt = 0; for(;(nb[tp]&i)!=nb[tp];tp--); for(int t,p;rsta;rsta-=t){ t = rsta &- rsta; p = lg[t]; int rp = cnt + (p >= v); g[tp+1][cnt] = g[tp][rp] - a[p][v]; h[tp+1][cnt] = h[tp][rp] + a[v][p]; cnt++; } nb[++tp] = i; } int rsta = M-i-1 , t , cnt = 0; for(;rsta;rsta-=t){ t = rsta & -rsta; f[i|t] = min(f[i|t] , f[i] + g[tp][cnt] * (-bit[i]-1) + h[tp][cnt] * (bit[i]+1) + K * (bit[i] + 1) * (sm[lg[t]] - g[tp][cnt] - h[tp][cnt])); cnt++; } } printf("%d\n",f[M-1]); }

T2: tree

It's very stiff.
01trie01trie01trie merge + global + 1 + 1 + 1.
Code\mathcal CodeCode

#include<bits/stdc++.h> #define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++) #define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--) #define pb push_back #define LL long long #define Ct const #define db double #define mp make_pair #define maxn 1058576 #define maxp maxn * 25 using namespace std; char cb[1<<16],*cs=cb,*ct=cb; #define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<16,stdin),cs==ct)?0:*cs++) void read(int &res){ char ch;bool f=0; for(;!isdigit(ch=getc());) if(ch=='-') f=1; for(res=ch-'0';isdigit(ch=getc());res=res*10+ch-'0'); (f) && (res=-res); } int n,v[maxn],fa[maxn]; vector<int>G[maxn]; int rt[maxn],ch[maxp][2],sm[maxp],sz[maxp],tot; void upd(int u,int d){ if(!u) return; sm[u] = sm[ch[u][0]] ^ sm[ch[u][1]] ^ (sz[ch[u][1]] ? 1 << d : 0); sz[u] = sz[ch[u][0]] ^ sz[ch[u][1]]; } void merge(int &u,int l,int r,int d){ if(!l || !r) return (void)(u = l+r); u = l; if(!ch[l][0] && !ch[l][1]){ sm[l] ^= sm[r]; sz[l] ^= sz[r]; return; } merge(ch[u][0],ch[l][0],ch[r][0],d+1),merge(ch[u][1],ch[l][1],ch[r][1],d+1); upd(u,d); } void add1(int u,int d){ if(!u) return; swap(ch[u][0],ch[u][1]); add1(ch[u][0],d+1); upd(u,d); } void ins(int &u,int v,int d){ if(!u) u = ++tot; if(d == 21) return (void)(sz[u] ^= 1); ins(ch[u][v>>d&1],v,d+1); upd(u,d); } LL ans; void dfs(int u){ rep(i,0,G[u].size()-1){ int v = G[u][i]; dfs(v); merge(rt[u] , rt[u] , rt[v] , 0); } add1(rt[u],0); ins(rt[u],v[u],0); ans += sm[rt[u]]; } int main(){ read(n); rep(i,1,n) read(v[i]); rep(i,2,n) read(fa[i]),G[fa[i]].pb(i); dfs(1); printf("%lld\n",ans); }

T3: assignment

Actually, it's very sb.
Mobius inversion, and then find the sum of edge weights, and use 1+wx1+wx1+wx to express the final [x1][x^1][x1], that is to say, you can do o (N3) O (N3) O (N3) O (N3) matrix tree theorem by mod x2\bmod x^2modx2.
We only make the matrix tree theorem when there are at least n − 1n-1n − 1 edges.
So the complexity is O(n3mdn)O(n^3 \frac n)O(n3nmd), where ddd is the number of factors, up to more than 100.
That is to say, when m=O(n2)m=O(n^2)m=O(n2), O(n4d)O(n^4d)O(n4d) barely gets stuck, which is actually very fast,
Almost O(n5d)O(n^5d)O(n5d) I don't know how to card. (that is to enumerate an edge deletion and then run the matrix tree to find the edge weight sum.)

Code\mathcal CodeCode

#include<bits/stdc++.h> #define maxn 33 #define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++) #define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--) #define mod 998244353 #define Ct const #define pb push_back using namespace std; int upd(int x){ return x += x >> 31 & mod; } int Pow(int b,int k){ int r=1;for(;k;k>>=1,b=1ll*b*b%mod) if(k&1) r=1ll*r*b%mod; return r; } struct data{ int a,b; data(Ct int &a=0,Ct int &b=0):a(a),b(b){} data operator +(Ct data &B)Ct{ return data(upd(a+B.a-mod),upd(b+B.b-mod)); } data operator -(Ct data &B)Ct{ return data(upd(a-B.a),upd(b-B.b)); } data operator *(Ct data &B)Ct{ return data(1ll * a * B.a % mod , (1ll * b * B.a + 1ll * a * B.b) % mod); } data operator *(Ct int &B)Ct{ return data(1ll * a* B % mod , 1ll * b * B % mod); } }a[maxn][maxn]; int n,m,sx[505],ty[505],cw[505]; #define maxv 160000 int phi[maxv],pr[maxv],cnt_pr,vis[maxv]; vector<int>G[160000]; int main(){ scanf("%d%d",&n,&m); rep(i,1,m){ scanf("%d%d%d",&sx[i],&ty[i],&cw[i]); for(int j=1;j*j<=cw[i];j++) if(cw[i] % j == 0){ G[j].pb(i); if(cw[i] != j * j) G[cw[i] / j].pb(i); } } phi[1] = 1; for(int i=2;i<maxv;i++){ if(!vis[i]) pr[cnt_pr++] = i , phi[i] = i-1; for(int j=0;pr[j] * i < maxv;j++){ vis[i * pr[j]] = 1; if(i % pr[j] == 0){ phi[i * pr[j]] = phi[i] * pr[j]; break; } phi[i * pr[j]] = phi[i] * (pr[j] - 1); } } int ans = 0;bool flg = 0; rep(i,1,maxv-1) if(G[i].size() >= n-1){ memset(a,0,sizeof a); rep(j,0,G[i].size()-1){ int v = G[i][j] , x = sx[v] , y = ty[v] , w = cw[v]; a[x][x] = (a[x][x] + data(1,w)) , a[y][y] = (a[y][y] + data(1,w)); a[x][y] = (a[x][y] - data(1,w)) , a[y][x] = (a[y][x] - data(1,w)); } data ret = data(1,0); rep(i,1,n-1){ if(!a[i][i].a) rep(j,i+1,n-1) if(a[j][i].a){ swap(a[j],a[i]); break; } ret = ret * a[i][i]; if(!a[i][i].a && !a[i][i].b){ ret = data(0,0); break; } if(!a[i][i].a){ flg = 1; data iv = data(Pow(a[i][i].b , mod-2),0); rep(j,i,n-1) a[i][j] = a[i][j] * iv; rep(j,i+1,n-1) if(a[j][i].a || a[j][i].b){ data t = data(a[j][i].b,0); rep(k,i,n-1) a[j][k] = (a[j][k] - a[i][k] * t); } } else{ data iv = data(a[i][i].a , mod-a[i][i].b) * Pow(a[i][i].a , mod-3); rep(j,i,n-1) a[i][j] = a[i][j] * iv; rep(j,i+1,n-1) if(a[j][i].a || a[j][i].b){ data t = a[j][i]; rep(k,i,n-1) a[j][k] = (a[j][k] - a[i][k] * t); } } } ans = (ans + 1ll * ret.b * phi[i]) % mod; } printf("%d\n",(ans+mod)%mod); }

I don't know how to turn it over. I hope I can get 5 points

21 June 2020, 23:50 | Views: 6088

Add new comment

For adding a comment, please log in
or create account

0 comments