TJOI2018游记
D1T1 - 数学计算
直接用线段树/平衡树维护所有数的积即可。我思想僵化写了一个数学方法...应该是能做\(\bmod\)所有数的乘除法。
时间复杂度\(O(nlogn)\)。
D1T2 - 智力竞赛
二分答案+最小可相交路径覆盖。题意有点乱...
D1T3 - party
Icefox orz 是我不会的DDP呢。首先列出最长公共子序列的DP方程,\(dp[i][j]\)表示\(a_1\)的前\(i\)位与\(a_2\)的前\(j\)位的LCS长度:
\[ dp[i][j]=max(dp[i-1][j],dp[i][j-1],dp[i-1][j-1]+[a_1[i]=a_2[j]]) \] 观察到\(dp[i][j]\)只会比\(dp[i][j-1]\)大0/1,所以将这个DP数组压成一个二进制数进行DP。\(f[i][s]\)表示对于一个长度为\(i\)的兑奖串,此时的DP数组的状态为\(s\)时的方案数。预处理出DP数组根据第\(i\)位的选择会转移到什么状态,就可以做啦。由于要求不能出现“NOI”所以再加一维记录前两位的状态就好啦。
时间复杂度\(O(n2^k)\)。
D2T1 - str
\(dp[i][j]\)表示用了前\(i\)种串,在位置\(j\)匹配结束的串的个数。那么对于第\(i+1\)种串用KMP得到其能匹配在哪些位置,就可以转移到\(dp[i+1]\)了。
时间复杂度\(O(|s|\Sigma a)\)。
D2T2 - xor
基本是个可持久化trie树裸题。不过好像Windows下DFS会爆栈?
时间复杂度\(O(n+30Q)\)。
D3T3 - 教科书般的亵渎
玩过炉石的应该很容易看懂题。再加上我最近经常玩变节咆哮魔亵渎术233
最终目标是求\(S(n,k)=\sum_{i=1}^n i^k\)。有两种方法:
\[\begin{align*}
(n+1)^{k+1}-n^{k+1} &= \binom{k+1}{1}n^k+\binom{k+1}{2}n^{k-1}+...+\binom{k+1}{k+1}n^0 \\
n^{k+1}-(n-1)^{k+1} &= \binom{k+1}{1}(n-1)^k+\binom{k+1}{2}(n-1)^{k-1}+...+\binom{k+1}{k+1}(n-1)^0 \\
&... \\
2^{k+1}-1^{k+1} &= \binom{k+1}{1}1^k+\binom{k+1}{2}1^{k-1}+...+\binom{k+1}{k+1}1^0 \\
\end{align*}\] 相加,得
\[\begin{align*}
(n+1)^{k+1}-1 &= \binom{k+1}{1}S(n,k)+\binom{k+1}{2}S(n,k-1)+...+\binom{k+1}{k+1}S(n,0) \\
S(n,k) &= \frac{1}{k+1}((n+1)^{k+1}-\sum_{i=2}^{k+1}\binom{k+1}{i}S(n,k+1-i)-1)
\end{align*}\] 于是我们就可以在\(O(k^2)\)的时间内求出\(S(n,k)\)。
另一种做法是利用伯努利数。
首先有
\[ S(n,k)= \frac{1}{k+1} \sum_{i=1}^{k+1}\binom{k+1}{i}B_{k+1-i}(n+1)^i \]其中\(B\)是伯努利数,伯努利数满足\(B_0=1\),对于\(n>0\)有
\[ \sum_{i=0}^{n}\binom{n+1}{i}B_i=0 \] 然后就可以求了。不要问我为什么,我也不知道!
Code
D1T1
#include <cstdio> typedef long long lint; inline char gc() { static char now[1<<16],*s,*t; if(s==t) {t=(s=now)+fread(now,1,1<<16,stdin); if(s==t) return EOF;} return *s++; } inline int read() { int x=0; char ch=gc(); while(ch<'0'||'9'<ch) ch=gc(); while('0'<=ch&&ch<='9') x=x*10+ch-'0',ch=gc(); return x; } const int N=1e4+10; const int N1=1e5+10; int cntP,pr[N1]; bool notP[N1]; int p1[N1],phi[N1]; void init() { phi[1]=1; for(lint i=2;i<=1e5;i++) { if(!notP[i]) { pr[++cntP]=i; p1[i]=i,phi[i]=i-1; for(lint j=i*i;j<=1e5;j*=i) p1[j]=j,phi[j]=(i-1)*(j/i); } for(int j=1;j<=cntP;j++) { if(i*pr[j]>1e5) break; int x=i*pr[j]; notP[x]=true; if(i%pr[j]) p1[x]=pr[j],phi[x]=phi[i]*(pr[j]-1); else {p1[x]=p1[i]*pr[j],phi[x]=phi[p1[x]]*phi[x/p1[x]]; break;} } } } int pow(int x,int y,int P) { while(x<0) x+=P; lint r=1,t=x; for(int i=y;i;i>>=1,t=t*t%P) if(i&1) r=r*t%P; return r; } int cnt,p ,q ; lint m ,a ,k ; int getX() { int a1=0,m1=1,phi1=1; for(int i=1;i<=cnt;i++) { int m2=m[i],a2=(k[i]>=q[i])?0:(a[i]*pow(p[i],k[i],m[i])); int phi2=(p[i]-1)*(m[i]/p[i]); lint t=1LL*a1*m2-1LL*a2*m1; while(t<0) t+=m1*m2; a1=t*pow(m2-m1,phi1*phi2-1,m1*m2)%(m1*m2); m1=m1*m2; phi1=phi1*phi2; } return a1; } int pos[N1]; void work0(int Q,int P) { int ans=1; for(int owo=1;owo<=Q;owo++) { int opt=read(),x=read(); pos[owo]=x; if(opt==1) ans=(lint)ans*x%P; else ans=(lint)ans*pow(pos[x],P-2,P)%P; printf("%d\n",ans); } } int main() { freopen("cal.in","r",stdin); freopen("cal.out","w",stdout); int task=read(); init(); while(task--) { int Q=read(),mod=read(); cnt=0; for(int i=1,t=mod;i<=cntP+1;i++) { if(i==cntP+1&&t>1) { cnt++,p[cnt]=t,q[cnt]=1,m[cnt]=t,a[cnt]=1,k[cnt]=0; break; } if(t<pr[i]) break; if(t%pr[i]==0) cnt++,p[cnt]=pr[i],q[cnt]=0,m[cnt]=1,a[cnt]=1,k[cnt]=0; while(t%pr[i]==0) t/=pr[i],q[cnt]++,m[cnt]*=pr[i]; } if(cnt<=1) {work0(Q,mod); continue;} for(int owo=1;owo<=Q;owo++) { int opt=read(),x=read(); pos[owo]=x; if(opt==1) { for(int i=1;i<=cnt;i++) { int t=x; while(t%p[i]==0) t/=p[i],k[i]++; a[i]=(lint)a[i]*t%m[i]; } } else { for(int i=1;i<=cnt;i++) { int t=pos[x]; while(t%p[i]==0) t/=p[i],k[i]--; a[i]=(lint)a[i]*pow(t,(p[i]-1)*(m[i]/p[i])-1,m[i])%m[i]; } } //for(int i=1;i<=cnt;i++) printf("=%d (mod %d) k=%d\n",a[i],m[i],k[i]); printf("%d\n",getX()); } } return 0; }
D1T2
//智力竞赛 #include <algorithm> #include <cstdio> #include <cstring> using std::sort; inline char gc() { static char now[1<<16],*s,*t; if(s==t) {t=(s=now)+fread(now,1,1<<16,stdin); if(s==t) return EOF;} return *s++; } inline int read() { int x=0; char ch=gc(); while(ch<'0'||'9'<ch) ch=gc(); while('0'<=ch&&ch<='9') x=x*10+ch-'0',ch=gc(); return x; } const int N=600; int n,m,w ; bool ed ,e ; int map ; struct rec{int w,id;} r ; bool cmpW(rec x,rec y) {return x.w<y.w;} int n1; int link ; bool used ; bool find(int u) { for(int v=1;v<=n1;v++) { if(!e[u][v]||used[v]) continue; used[v]=true; if(!link[v]||find(link[v])) {link[v]=u; return true;} } return false; } int match() { int res=0; memset(link,0,sizeof link); for(int u=1;u<=n1;u++) { memset(used,0,sizeof used); if(find(u)) res++; } return res; } bool check(int x) { n1=x; memset(e,false,sizeof e); for(int u=1;u<=n1;u++) for(int v=1;v<=n1;v++) e[u][v]=ed[u][v]; for(int k=1;k<=n1;k++) for(int u=1;u<=n1;u++) for(int v=1;v<=n1;v++) e[u][v]|=e[u][k]&&e[k][v]; return n1-match()<=m; } int main() { freopen("contest.in","r",stdin); freopen("contest.out","w",stdout); m=read()+1,n=read(); for(int i=1;i<=n;i++) { r[i].w=read(),r[i].id=i; int x=read(); for(int j=1;j<=x;j++) e[i][read()]=true; } sort(r+1,r+n+1,cmpW); for(int i=1;i<=n;i++) w[i]=r[i].w,map[r[i].id]=i; for(int u=1;u<=n;u++) for(int v=1;v<=n;v++) if(e[u][v]) ed[map[u]][map[v]]=true; int L=1,R=n; while(L<=R) { int mid=L+R>>1; if(check(mid)) L=mid+1; else R=mid-1; } if(R<n) printf("%d\n",r[R+1].w); else puts("AK"); return 0; }
D1T3
//party #include <cstdio> #include <cstring> inline int max(int x,int y) {return x>y?x:y;} const int S=1<<16; const int P=1e9+7; int n,m,U; char s0[20]; int tr1[S][3],tr2[3][3]; int f1[20],f2[20]; int getDP(int x) { for(int i=1;i<=m;i++) f2[i]=max(f1[i-1]+(x==s0[i]),max(f1[i],f2[i-1])); int s=0; for(int i=1;i<=m;i++) s|=(f2[i]-f2[i-1])<<i-1; return s; } int dp[2][S][4]; int bitcnt(int s) {int r=0; while(s) r+=s&1,s>>=1; return r;} int ans[20]; int main() { freopen("party.in","r",stdin); freopen("party.out","w",stdout); scanf("%d%d",&n,&m); scanf("%s",s0+1); for(int i=1;i<=m;i++) if(s0[i]=='N') s0[i]=0; else if(s0[i]=='O') s0[i]=1; else s0[i]=2; U=(1<<m)-1; for(int s=0;s<=U;s++) { for(int i=1;i<=m;i++) f1[i]=f1[i-1]+((s>>i-1)&1); for(int k=0;k<3;k++) tr1[s][k]=getDP(k); } tr2[0][0]=1; tr2[1][0]=1,tr2[1][1]=2; tr2[2][0]=1,tr2[2][2]=3; int c=0; dp[c][0][0]=1; for(int i=1;i<=n;i++) { c^=1; for(int s1=0;s1<=U;s1++) for(int s2=0;s2<3;s2++) for(int k=0;k<3;k++) dp[c][tr1[s1][k]][tr2[s2][k]]+=dp[c^1][s1][s2],dp[c][tr1[s1][k]][tr2[s2][k]]%=P; memset(dp[c^1],0,sizeof dp[c^1]); } for(int s=0;s<=U;s++) ans[bitcnt(s)]=((long long)ans[bitcnt(s)]+dp[c][s][0]+dp[c][s][1]+dp[c][s][2])%P; for(int i=0;i<=m;i++) printf("%d\n",ans[i]); return 0; }
D2T1
//str #include <cstdio> #include <cstring> const int N=1e4+10; const int P=1e9+7; int n,k; char s ,s0[30]; int f[2] ; int nxt[30]; void getNxt(char s[]) { int len=strlen(s+1); nxt[0]=nxt[1]=0; for(int i=2;i<=len;i++) { int j=nxt[i-1]; while(j&&s[i]!=s[j+1]) j=nxt[j]; if(s[i]==s[j+1]) nxt[i]=j+1; else nxt[i]=0; } } int main() { freopen("str.in","r",stdin); freopen("str.out","w",stdout); scanf("%d",&k); scanf("%s",s+1),n=strlen(s+1); int c=0; for(int i=0;i<=n;i++) f[c][i]=1; for(int owo=0;owo<k;owo++,c^=1) { memset(f[c^1],0,sizeof f[c^1]); int cnt; scanf("%d",&cnt); while(cnt--) { scanf("%s",s0+1); getNxt(s0); int len=strlen(s0+1); for(int i=1,j=0;i<=n;i++) { while(j&&s[i]!=s0[j+1]) j=nxt[j]; if(s[i]==s0[j+1]) j++; if(j==len) f[c^1][i]=(f[c^1][i]+f[c][i-len])%P; } } } int ans=0; for(int i=0;i<=n;i++) ans=(ans+f[c][i])%P; printf("%d\n",ans); return 0; }
D2T2
//xor #include <algorithm> #include <cstdio> using namespace std; inline char gc() { static char now[1<<16],*s,*t; if(s==t) {t=(s=now)+fread(now,1,1<<16,stdin); if(s==t) return EOF;} return *s++; } inline int read() { int x=0; char ch=gc(); while(ch<'0'||'9'<ch) ch=gc(); while('0'<=ch&&ch<='9') x=x*10+ch-'0',ch=gc(); return x; } const int N=1e5+10; int n,w ; int edCnt,h ; struct edge{int v,nxt;} ed[N<<1]; void edAdd(int u,int v) { edCnt++; ed[edCnt].v=v,ed[edCnt].nxt=h[u],h[u]=edCnt; edCnt++; ed[edCnt].v=u,ed[edCnt].nxt=h[v],h[v]=edCnt; } int fa [20],dpt ; int dfCnt,dfn ,fr ,to ; void dfs(int u) { dfn[++dfCnt]=u; fr[u]=dfCnt; for(int k=1;k<=17;k++) fa[u][k]=fa[fa[u][k-1]][k-1]; for(int i=h[u];i;i=ed[i].nxt) { int v=ed[i].v; if(v==fa[u][0]) continue; fa[v][0]=u,dpt[v]=dpt[u]+1,dfs(v); } to[u]=dfCnt; } inline lca(int u,int v) { if(dpt[u]<dpt[v]) swap(u,v); for(int k=17;k>=0;k--) if(dpt[fa[u][k]]>=dpt[v]) u=fa[u][k]; if(u==v) return u; for(int k=17;k>=0;k--) if(fa[u][k]!=fa[v][k]) u=fa[u][k],v=fa[v][k]; return fa[u][0]; } const int N1=N*31; int rt1 ,rt2 ; int ndCnt,ch[N1][2],siz[N1]; inline void ndCopy(int p,int &q) {ch[p][0]=ch[q][0],ch[p][1]=ch[q][1],siz[p]=siz[q];} void ins(int &p,int x,int d) { ndCopy(++ndCnt,p); p=ndCnt; siz[p]++; if(d<0) return; int t=(x>>d)&1; ins(ch[p][t],x,d-1); } void bldTr2(int u) { ins(rt2[u]=rt2[fa[u][0]],w[u],30); for(int i=h[u];i;i=ed[i].nxt) { int v=ed[i].v; if(v!=fa[u][0]) bldTr2(v); } } int qres; void query1(int p1,int p2,int x) { int now=0; for(int d=30;d>=0;d--) { int t=((x>>d)&1)^1,sizT=siz[ch[p2][t]]-siz[ch[p1][t]]; if(!sizT) t^=1; p1=ch[p1][t],p2=ch[p2][t],now|=t<<d; } qres=x^now; } void query2(int p1,int p2,int p3,int x) { int now=0; for(int d=30;d>=0;d--) { int t=((x>>d)&1)^1,sizT=siz[ch[p1][t]]+siz[ch[p2][t]]-siz[ch[p3][t]]*2; if(!sizT) t^=1; p1=ch[p1][t],p2=ch[p2][t],p3=ch[p3][t],now|=t<<d; } qres=x^now; } void show(int p) { if(!p) return; printf("%2d siz=%d ch=%d,%d\n",p,siz[p],ch[p][0],ch[p][1]); show(ch[p][0]); show(ch[p][1]); } int main() { freopen("xor.in","r",stdin); freopen("xor.out","w",stdout); n=read(); int Q=read(); for(int i=1;i<=n;i++) w[i]=read(); for(int i=1;i<=n-1;i++) { int u=read(),v=read(); edAdd(u,v); } fa[1][0]=0,dpt[1]=1,dfs(1); for(int i=1;i<=n;i++) ins(rt1[i]=rt1[i-1],w[dfn[i]],30); bldTr2(1); /*for(int i=1;i<=n;i++) show(rt1[i]),puts(""); puts(""); for(int i=1;i<=n;i++) show(rt2[i]),puts("");*/ while(Q--) { int opt=read(); if(opt==1) { int u=read(),x=read(); qres=0; query1(rt1[fr[u]-1],rt1[to[u]],x); } else { int u=read(),v=read(),x=read(); int t=lca(u,v); qres=0; query2(rt2[u],rt2[v],rt2[t],x); qres=max(qres,w[t]^x); } printf("%d\n",qres); } return 0; }
D2T3
//教科书般的亵渎 #include <algorithm> #include <cstdio> using std::sort; typedef long long lint; inline lint read() { lint x=0; char ch=getchar(); while(ch<'0'||'9'<ch) ch=getchar(); while('0'<=ch&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x; } const int P=1e9+7; const int M=60; lint n,a[M]; int m; int B[M],C[M][M],inv[M]; void init(int n) { inv[1]=1; for(int i=2;i<=n;i++) inv[i]=1LL*inv[P%i]*(P-P/i)%P; for(int i=0;i<=n;i++) { C[i][0]=1; for(int j=1;j<=i;j++) C[i][j]=(C[i-1][j-1]+C[i-1][j])%P; } B[0]=1; for(int i=1;i<=n-1;i++) { B[i]=0; for(int j=0;j<=i-1;j++) B[i]=(B[i]+1LL*C[i+1][j]*B[j])%P; B[i]=(1LL*(P-B[i])*inv[i+1])%P; } } int pow(lint x,int y) { lint r=1,t=x; for(int i=y;i;i>>=1,t=t*t%P) if(i&1) r=r*t%P; return r; } int S(lint n) { int s=0; for(int i=1;i<=m+1;i++) s=(s+1LL*C[m+1][i]*B[m+1-i]%P*pow(n+1,i)%P)%P; s=1LL*s*inv[m+1]%P; //printf("Sigma(%d,%d)=%d\n",n,m,s); return s; } int main() { freopen("defile.in","r",stdin); freopen("defile.out","w",stdout); init(59); int task=read(); while(task--) { n=read(),m=read(); for(int i=1;i<=m;i++) a[i]=read(); a[++m]=++n; sort(a+1,a+m+1); lint ans=0; for(int i=1;i<=m;i++) { for(int j=i;j<=m;j++) ans=(ans+S(a[j]-1)-S(a[j-1])+P)%P; for(int j=i+1;j<=m;j++) a[j]-=a[i]; a[i]=0; } printf("%lld\n",ans); } return 0; }
- JSOI 2018 Round 1 游记
- APIO 2018 游记
- 洛谷P4593 [TJOI2018]教科书般的亵渎 【数学】
- # 2018高考&自主招生 - 游记
- BZOJ_5338_ [TJOI2018]xor_可持久化trie
- WC2018 游记
- 可持久化01Trie树+LCA【p4592】[TJOI2018]异或
- CCPC2018秦皇岛游记
- PKUWC 2018 游记
- BZOJ5334:[TJOI2018]数学计算——题解
- BZOJ5336:[TJOI2018]游园会——题解
- 前尘浮华一场梦 NOI2018 游记
- BZOJ5338 [TJOI2018] Xor 【可持久化Trie树】【dfs序】
- CTSC2018 && APIO2018 游记
- ZJOI2018游记
- BZOJ5334 [TJOI2018] 数学计算 【线段树分治】
- Codechef September Challenge 2018 游记
- WC2018游记
- WC2018 游记
- BZOJ5335 : [TJOI2018]智力竞赛