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 ```cpp #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[N],q[N]; lint m[N],a[N],k[N]; 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 ```cpp //智力竞赛 #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[N]; bool ed[N][N],e[N][N]; int map[N]; struct rec{int w,id;} r[N]; bool cmpW(rec x,rec y) {return x.w<y.w;} int n1; int link[N]; bool used[N]; 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 ```cpp //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 ```cpp //str #include <cstdio> #include <cstring> const int N=1e4+10; const int P=1e9+7; int n,k; char s[N],s0[30]; int f[2][N]; 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 ```cpp //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[N]; int edCnt,h[N]; 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[N][20],dpt[N]; int dfCnt,dfn[N],fr[N],to[N]; 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[N],rt2[N]; 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 ```cpp //教科书般的亵渎 #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; } ```\]

posted @ 2018-05-04 08:22  VisJiao  阅读(828)  评论(1编辑  收藏  举报