WC2019 数树

  • 解决了一个心头大患
  • 考试的时候本人太智障了QwQ
  • 本文的参考链接,膜了一发rqy的题解

题目链接

Subtask 0

好像可以直接做...

推一推就能发现,是$y^k$,其中$k$表示相同的边构成的联通块数...

(我在考试的时候,丝毫都没有意识到这是$n-边数$

namespace Subtask1
{
int main()
{
int cnt=n;
for(int x=1;x<=n;x++)
{
for(int i=head[x];i!=-1;i=e[i].next)
{
int to1=e[i].to;
if(to1<x&&mp[x].find(to1)!=mp[x].end())cnt--;
}
}
printf("%d\n",q_pow(y,cnt));
return 0;
}
}

Subtask 1

这个就很麻烦了qwq

我们知道,$ans=y^{n-|E_1 \cap E_2|}$

通过简单容斥原理,我们可以得到:$f(S)=\sum\limits_{T\subseteq S}\sum\limits_{P\subseteq T}(-1)^{|T|-|P|}\times f(P)$

对于这样的问题,有一个简易的想法,就是枚举相同边集,也就是$f(S)=y^{n-|S|},S=E_1\cap E_2$

那么答案就是:$\sum\limits_{E_2}y^{n-|E_1\cap E_2|}=\sum\limits_{E_2}\sum\limits_{S\subseteq|E_1 \cap E_2|}\sum\limits_{P\subseteq S}(-1)^{|S|-|P|}\times y^{n-|P|}$

那么考虑变换枚举顺序:$\sum\limits_{S\subseteq E_1}(\sum\limits_{P\subseteq S}(-1)^{|S|-|P|}\times y^{n-|P|})\sum\limits_{E_2}[S\subseteq E_2]$

对于最后一项,表达的是包含$S$边集的生成树的个数,根据Prufer序列凯莱公式可以得到:$\sum\limits_{S\subseteq E_1}(n^{n-|S|-2}\times \prod\limits_{i=1}^{n-|S|} a_i) \sum\limits_{P\subseteq S}(-1)^{|S|-|P|}\times y^{n-|P|}$,其中$a_i$表示每个联通块的大小

为了方便表示,我们设:$g(S)=n{n-|S|-2}\times\prod\limits_{i=1}K a_i $

然后考虑如何去掉$P$的枚举,对于$(1-y)k=\sum\limits_{i=0}k C(k,i)\times (-1)^i\times y^i=\sum\limits_{S\subseteq T}(-y)^{|S|}$,其中$|T|=k$

所以我们考虑将$y^{n-|P|}$转化一下得到:$\sum\limits_{S\subseteq E_1}g(S)\times y^{n-|S|}\sum\limits_{P\subseteq S}(-y)^{|S|-|P|}$

那么对于上面的式子可以变成:$\sum\limits_{S\subseteq E_1} g(S)\times y^{n-|S|}\times (1-y)^{|S|}$

然后展开$g(S)$:$\sum\limits_{S\subseteq E_1} n^{n-|S|-2}\times y^{n-|S|}\times (1-y)^{|S|} \prod\limits_{i=1}^{n-|S|} a_i $

设:$n-|S|=k$

那么:$\sum\limits_{S\subseteq E_1}n^{k-2}\times y^k\times (1-y)^{n-k}\times \prod\limits_{i=1}^ka_i$

然后把$(1-y){n-k},n{k-2}$转化一下,提出去可以得到:$\frac{(1-y)n}{n2}\sum\limits_{S\subseteq E_1} (\frac{n\times y}{1-y})^k \prod\limits_{i=1}^k a_i$

然后设:$K=\frac{n\times y}{1-y}$,忽略掉前面的常数:$\sum\limits_{S\subseteq E_1}K^k \prod\limits_{i=1}^k a_i=\sum\limits_{S\subseteq E_1}\prod\limits_{i=1}^k a_i\times K$

那么相当于是对于每个联通块有大小乘以$K$的贡献,这个东西显然可以树形背包...

但是这样是$n^2$的,非常讲道理...

那我们考虑背包的多项式有没有什么神奇的性质...

对于答案,我们设:$g(x)=K\sum\limits_{i=1} i\times f_x(i)$

设:$F_p(x)=\sum\limits_{i=1}x^i\times f_p(i)$

那么显然$g(x)=K\times F_x'(1)$

对于$F_u(x)$的转移很显然,$F_u(x)=x\prod\limits_{v}(F_v(x)+g(v))$

那么根据导数的定义:$g(u)=K\times \prod\limits_{v}(F_v(1)+g(v))+(\prod\limits_{v} (F_v(1)+g(v)))\sum\limits_{v}\frac{K\times F_v'(1)}{g(v)+F_v(1)}$

那么我们发现,如果需要维护$g(x)$那么只需要维护$F_x(1)$即可。

所以设:$f(x)=F_x(1)$,因此:$g(u)=f(u)\times (K+\sum\limits_{v} \frac{g(v)}{g(v)+f(v)})$

那么就完事了qwq

namespace Subtask2
{
int f[N],g[N],K;
void dfs(int x,int from)
{
g[x]=K,f[x]=1;
for(int i=head[x];i!=-1;i=e[i].next)
{
int to1=e[i].to;
if(to1!=from)
{
dfs(to1,x);
g[x]=(g[x]+(ll)g[to1]*inv(g[to1]+f[to1]))%mod;
f[x]=(ll)f[x]*(g[to1]+f[to1])%mod;
}
}
g[x]=(ll)g[x]*f[x]%mod;
}
int main()
{
if(y==1)return printf("%d\n",q_pow(n,n-2)),0;
K=(ll)n*y%mod*inv(1-y)%mod;dfs(1,0);
printf("%lld\n",((ll)g[1]*q_pow(n,mod-3)%mod*q_pow(1-y,n)%mod+mod)%mod);
return 0;
}
}

Subtask 2

根据上面的容斥原理,我们想到一个绝妙的方法,那就是俩都枚举一下试试

$\sum\limits_{S}g(S)^2 \times y^{n-|S|}\times (1-y)^{|S|}$

然后同样展开qwq

$\frac{(1-y)n}{n4}\sum\limits_S \prod\limits_{i=1}^k a_i^2 \frac{n^2 \times y}{1-y}$

然后同样设:$K=\frac{n^2\times y}{1-y}$

同样发现,可以得到:$\frac{(1-y)n}{n4}\sum\limits_{S}\prod\limits_{i=1}^k a_i^2\times K$

然后.........麻麻我不会了..........

那么证明,我们不能通过枚举边集来解决...

所以,我们考虑所有的联通块具有什么样的性质,显然,他们所有联通块的点数之和恰好为$n$,好吧,这是一句废话qwq

对于这样的形式,我们可以考虑枚举每个联通块也就是说,我们可以得到:$\frac{(1-y)n}{n4}\sum\limits_{(\sum\limits_{i=1}^k a_i)=n}\frac{1}{k!}\prod\limits_{i=1}^k \frac{a_i^{a_i-2}}{a_i!}\times a_i^2\times K$

那么稍微化简化简:$\frac{(1-y)n}{n4}\sum\limits_{(\sum\limits_{i=1}^k a_i)=n}\frac{1}{k!}\prod\limits_{i=1}^k K \times\frac{a_i^{a_i}}{a_i!}$

我们发现:多项式出现了!

$ \frac{(1-y)n}{n4}[ x^n ] (\sum\limits_{k=1} \frac{1}{k!} \prod\limits_{i=1}^k f(x)) $,其中,$ f(x)=\sum\limits_{i=1} \frac{i^i}{i!} x^i $

然后可以发现,前面的式子就是:$\frac{(1-y)n}{n4} [ x^n ] ( \sum\limits_{k=1} \frac{1}{k!} f(x)^k )$

然后,对于$e^x$麦克劳林展开:$\sum\limits_{i=0} \frac{x^k}{i!}$

那么对于后面的那个式子,本质就是$e^{f(x)}$

那么直接多项式exp就好了qwq

namespace Subtask3
{
int A[N<<2],B[N<<2];
void NTT(int *a,int len,int flag)
{
int i,j,k,t,w,x,tmp;
for(i=k=0;i<len;i++)
{
if(i>k)swap(a[i],a[k]);
for(j=len>>1;(k^=j)<j;j>>=1);
}
for(k=2;k<=len;k<<=1)
{
t=k>>1;x=q_pow(3,(mod-1)/k);if(flag==-1)x=inv(x);
for(i=0;i<len;i+=k)
for(w=1,j=i;j<i+t;j++,w=(ll)w*x%mod)
tmp=(ll)w*a[j+t]%mod,a[j+t]=(a[j]-tmp)%mod,a[j]=(a[j]+tmp)%mod;
}if(flag==-1)for(t=inv(len),i=0;i<len;i++)a[i]=(ll)a[i]*t%mod;
}
struct poly
{
vector<int >a;int len;
poly(){a.clear();len=0;}
poly(int x){a.clear();a.push_back(x);len=1;}
void resize(int x){a.resize(x);for(int i=len;i<x;i++)a[i]=0;len=x;}
poly operator * (const poly &b) const
{
poly c=poly();c.resize(len+b.len-1);
if(c.len<=200)
{
for(int i=0;i<len;i++)
for(int j=0;j<b.len;j++)
c.a[i+j]=(c.a[i+j]+(ll)a[i]*b.a[j])%mod;
return c;
}
int n=1,i;while(n<c.len)n<<=1;
for(i=0;i<len;i++)A[i]=a[i];for(i=len;i<n;i++)A[i]=0;
for(i=0;i<b.len;i++)B[i]=b.a[i];for(i=b.len;i<n;i++)B[i]=0;
NTT(A,n,1);NTT(B,n,1);for(i=0;i<n;i++)A[i]=(ll)A[i]*B[i]%mod;NTT(A,n,-1);
for(i=0;i<c.len;i++)c.a[i]=A[i];return c;
}
poly operator + (const poly &b) const
{
poly c=poly();c.resize(max(b.len,len));
for(int i=0;i<len;i++)c.a[i]=a[i];
for(int i=0;i<b.len;i++)(c.a[i]+=b.a[i])%=mod;
return c;
}
poly operator - (const poly &b) const
{
poly c=poly();c.resize(max(b.len,len));
for(int i=0;i<len;i++)c.a[i]=a[i];
for(int i=0;i<b.len;i++)(c.a[i]-=b.a[i])%=mod;
return c;
}
void get_inv(poly &b,int n)
{
if(n==1)return void(b=poly(inv(a[0])));get_inv(b,n>>1);int t=n<<1,lim=min(n,len);
for(int i=0;i<lim;i++)A[i]=a[i];for(int i=lim;i<t;i++)A[i]=0;
for(int i=0;i<b.len;i++)B[i]=b.a[i];for(int i=b.len;i<t;i++)B[i]=0;
NTT(A,t,1);NTT(B,t,1);for(int i=0;i<t;i++)B[i]=(2-(ll)A[i]*B[i]%mod)*B[i]%mod;NTT(B,t,-1);
b.resize(n);for(int i=0;i<n;i++)b.a[i]=B[i];
}
poly Dao(){poly c=poly();c.resize(len-1);for(int i=1;i<len;i++)c.a[i-1]=(ll)i*a[i]%mod;return c;}
poly Int(){poly c=poly();c.resize(len+1);for(int i=0;i<len;i++)c.a[i+1]=(ll)a[i]*inv(i+1)%mod;return c;}
poly get_ln(int n)
{
poly c=poly();get_inv(c,n);
c=(c*Dao()).Int();c.resize(n);
return c;
}
void print(){printf("lenth = %d\n",len);for(int i=0;i<len;i++)printf("%d ",a[i]);puts("");}
}a,b;
void get_exp(const poly &a,poly &b,int len)
{
if(len==1){b=poly(1);return ;}get_exp(a,b,len>>1);
poly c=a-b.get_ln(len);c.a[0]++;c.resize(len);b=b*c;b.resize(len);
}
int fac[N],inv[N];
int main()
{
if(y==1)return printf("%d\n",q_pow(n,2*(n-2))),0;
fac[0]=1;for(int i=1;i<=n;i++)fac[i]=(ll)fac[i-1]*i%mod;
inv[n]=inv(fac[n]);for(int i=n;i;i--)inv[i-1]=(ll)inv[i]*i%mod;
int K=(ll)n*n%mod*y%mod*inv(1-y)%mod;a.resize(n+1);
for(int i=1;i<=n;i++)a.a[i]=(ll)q_pow(i,i)*inv[i]%mod*K%mod;
int len=1;while(len<(n+1))len<<=1;get_exp(a,b,len);
printf("%lld\n",((ll)b.a[n]*fac[n]%mod*q_pow(n,mod-5)%mod*q_pow(1-y,n)%mod+mod)%mod);
return 0;
}
}

然后完整代码如下:

#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <queue>
#include <iostream>
#include <bitset>
#include <map>
using namespace std;
#define N 100005
#define ll long long
#define mod 998244353
struct node{int to,next;}e[N<<1];
int n,head[N],y,op,cnt;
void add(int x,int y){e[cnt]=(node){y,head[x]};head[x]=cnt++;}
int q_pow(int x,int n){int ret=1;for(;n;n>>=1,x=(ll)x*x%mod)if(n&1)ret=(ll)ret*x%mod;return ret;}
#define inv(x) q_pow(x,mod-2)
map<int ,int >mp[N];
namespace Subtask1
{
int main()
{
int cnt=n;
for(int x=1;x<=n;x++)
{
for(int i=head[x];i!=-1;i=e[i].next)
{
int to1=e[i].to;
if(to1<x&&mp[x].find(to1)!=mp[x].end())cnt--;
}
}
printf("%d\n",q_pow(y,cnt));
return 0;
}
}
namespace Subtask2
{
int f[N],g[N],K;
void dfs(int x,int from)
{
g[x]=K,f[x]=1;
for(int i=head[x];i!=-1;i=e[i].next)
{
int to1=e[i].to;
if(to1!=from)
{
dfs(to1,x);
g[x]=(g[x]+(ll)g[to1]*inv(g[to1]+f[to1]))%mod;
f[x]=(ll)f[x]*(g[to1]+f[to1])%mod;
}
}
g[x]=(ll)g[x]*f[x]%mod;
}
int main()
{
if(y==1)return printf("%d\n",q_pow(n,n-2)),0;
K=(ll)n*y%mod*inv(1-y)%mod;dfs(1,0);
printf("%lld\n",((ll)g[1]*q_pow(n,mod-3)%mod*q_pow(1-y,n)%mod+mod)%mod);
return 0;
}
}
namespace Subtask3
{
int A[N<<2],B[N<<2];
void NTT(int *a,int len,int flag)
{
int i,j,k,t,w,x,tmp;
for(i=k=0;i<len;i++)
{
if(i>k)swap(a[i],a[k]);
for(j=len>>1;(k^=j)<j;j>>=1);
}
for(k=2;k<=len;k<<=1)
{
t=k>>1;x=q_pow(3,(mod-1)/k);if(flag==-1)x=inv(x);
for(i=0;i<len;i+=k)
for(w=1,j=i;j<i+t;j++,w=(ll)w*x%mod)
tmp=(ll)w*a[j+t]%mod,a[j+t]=(a[j]-tmp)%mod,a[j]=(a[j]+tmp)%mod;
}if(flag==-1)for(t=inv(len),i=0;i<len;i++)a[i]=(ll)a[i]*t%mod;
}
struct poly
{
vector<int >a;int len;
poly(){a.clear();len=0;}
poly(int x){a.clear();a.push_back(x);len=1;}
void resize(int x){a.resize(x);for(int i=len;i<x;i++)a[i]=0;len=x;}
poly operator * (const poly &b) const
{
poly c=poly();c.resize(len+b.len-1);
if(c.len<=200)
{
for(int i=0;i<len;i++)
for(int j=0;j<b.len;j++)
c.a[i+j]=(c.a[i+j]+(ll)a[i]*b.a[j])%mod;
return c;
}
int n=1,i;while(n<c.len)n<<=1;
for(i=0;i<len;i++)A[i]=a[i];for(i=len;i<n;i++)A[i]=0;
for(i=0;i<b.len;i++)B[i]=b.a[i];for(i=b.len;i<n;i++)B[i]=0;
NTT(A,n,1);NTT(B,n,1);for(i=0;i<n;i++)A[i]=(ll)A[i]*B[i]%mod;NTT(A,n,-1);
for(i=0;i<c.len;i++)c.a[i]=A[i];return c;
}
poly operator + (const poly &b) const
{
poly c=poly();c.resize(max(b.len,len));
for(int i=0;i<len;i++)c.a[i]=a[i];
for(int i=0;i<b.len;i++)(c.a[i]+=b.a[i])%=mod;
return c;
}
poly operator - (const poly &b) const
{
poly c=poly();c.resize(max(b.len,len));
for(int i=0;i<len;i++)c.a[i]=a[i];
for(int i=0;i<b.len;i++)(c.a[i]-=b.a[i])%=mod;
return c;
}
void get_inv(poly &b,int n)
{
if(n==1)return void(b=poly(inv(a[0])));get_inv(b,n>>1);int t=n<<1,lim=min(n,len);
for(int i=0;i<lim;i++)A[i]=a[i];for(int i=lim;i<t;i++)A[i]=0;
for(int i=0;i<b.len;i++)B[i]=b.a[i];for(int i=b.len;i<t;i++)B[i]=0;
NTT(A,t,1);NTT(B,t,1);for(int i=0;i<t;i++)B[i]=(2-(ll)A[i]*B[i]%mod)*B[i]%mod;NTT(B,t,-1);
b.resize(n);for(int i=0;i<n;i++)b.a[i]=B[i];
}
poly Dao(){poly c=poly();c.resize(len-1);for(int i=1;i<len;i++)c.a[i-1]=(ll)i*a[i]%mod;return c;}
poly Int(){poly c=poly();c.resize(len+1);for(int i=0;i<len;i++)c.a[i+1]=(ll)a[i]*inv(i+1)%mod;return c;}
poly get_ln(int n)
{
poly c=poly();get_inv(c,n);
c=(c*Dao()).Int();c.resize(n);
return c;
}
void print(){printf("lenth = %d\n",len);for(int i=0;i<len;i++)printf("%d ",a[i]);puts("");}
}a,b;
void get_exp(const poly &a,poly &b,int len)
{
if(len==1){b=poly(1);return ;}get_exp(a,b,len>>1);
poly c=a-b.get_ln(len);c.a[0]++;c.resize(len);b=b*c;b.resize(len);
}
int fac[N],inv[N];
int main()
{
if(y==1)return printf("%d\n",q_pow(n,2*(n-2))),0;
fac[0]=1;for(int i=1;i<=n;i++)fac[i]=(ll)fac[i-1]*i%mod;
inv[n]=inv(fac[n]);for(int i=n;i;i--)inv[i-1]=(ll)inv[i]*i%mod;
int K=(ll)n*n%mod*y%mod*inv(1-y)%mod;a.resize(n+1);
for(int i=1;i<=n;i++)a.a[i]=(ll)q_pow(i,i)*inv[i]%mod*K%mod;
int len=1;while(len<(n+1))len<<=1;get_exp(a,b,len);
printf("%lld\n",((ll)b.a[n]*fac[n]%mod*q_pow(n,mod-5)%mod*q_pow(1-y,n)%mod+mod)%mod);
return 0;
}
}
int main()
{
scanf("%d%d%d",&n,&y,&op);
if(op==2)return Subtask3::main();memset(head,-1,sizeof(head));
for(int i=1,x,y;i<n;i++)scanf("%d%d",&x,&y),add(x,y),add(y,x);
if(op==1)return Subtask2::main();
for(int i=1,x,y;i<n;i++)scanf("%d%d",&x,&y),mp[x][y]=mp[y][x]=1;
if(op==0)return Subtask1::main();
}

如果知道这个题的Subtask 2是多项式exp还行,如果不知道的话,硬想很难的qwq

然后Subtask 1的容斥才是本题的关键,Subtask 2算是锦上添花吧qwq

总体上,本题考查了$\min-\max$容斥(你仔细看看容斥式子,就是这个

考察了优化DP的一些技巧,同时搭配$prufer$序列的知识。

最后还考察了多项式exp的巧妙转化

是对选手数学功底的一个考验,显然对于我这种菜鸡就是挑战了qwq

然后还有一些奇妙的性质,总之,这是一个非常优秀的计数题目

最后,$Orz \ \ rqy$

BZOJ 5475: [WC 2019] 数树的更多相关文章

  1. 「WC 2019」数树

    「WC 2019」数树 一道涨姿势的EGF好题,官方题解我并没有完全看懂,尝试用指数型生成函数和组合意义的角度推了一波.考场上只得了 44 分也暴露了我在数数的一些基本套路上的不足,后面的 \(\ex ...

  2. 洛谷 P5206: bzoj 5475: LOJ 2983: [WC2019] 数树

    一道技巧性非常强的计数题,历年WC出得最好(同时可能是比较简单)的题目之一. 题目传送门:洛谷P5206. 题意简述: 给定 \(n, y\). 一张图有 \(|V| = n\) 个点.对于两棵树 \ ...

  3. [WC2019] 数树

    [WC2019] 数树 Zhang_RQ题解(本篇仅概述) 前言 有进步,只做了半天.... 一道具有极强综合性的数数好题! 强大的多合一题目 精确地数学推导和耐心. 有套路又不失心意. 融合了: 算 ...

  4. PKUWC 2019&WC 2019爆零记

    PKUWC 2019&WC 2019爆零记 毕竟过了很久了,杂七杂八的东西就不写了,并且除成绩之外的内容不保证其正确性. Day1 T1:看到这道题很舒服啊,枚举top序算合法图的数量,状压D ...

  5. WC 2019 游记 - 败者之低语

    败者之低语 WC 2019 游记 Day -1 看了一圈PKU和THU的题,感觉图像识别真有意思... 感觉非常讲道理,pku还是比thu简单一点的... 听说高二414在thu没有进面试? 震惊!( ...

  6. WC2019 T1 数树

    WC2019 T1 数树 传送门(https://loj.ac/problem/2983) Question 0 对于给定的两棵树,设记两颗树 \(A,B\) 的重边数量为 \(R(A,B)\),那么 ...

  7. Bzoj 2752 高速公路 (期望,线段树)

    Bzoj 2752 高速公路 (期望,线段树) 题目链接 这道题显然求边,因为题目是一条链,所以直接采用把边编上号.看成序列即可 \(1\)与\(2\)号点的边连得是. 编号为\(1\)的点.查询的时 ...

  8. [CSP-S 2019]括号树

    [CSP-S 2019]括号树 源代码: #include<cstdio> #include<cctype> #include<vector> inline int ...

  9. 【LOJ】#2983. 「WC2019」数树

    LOJ2983. 「WC2019」数树 task0 有\(i\)条边一样答案就是\(y^{n - i}\) task1 这里有个避免容斥的方法,如果有\(i\)条边重复我们要算的是\(y^{n - i ...

随机推荐

  1. 卸载Myeclipse10.5 报错“an error has occured.See the log file ...Uninstaller\...”

    找到Myeclipse的安装包,双击它,会出现Uninstaller的按钮,单击卸载即可. 另,网上说,windows下cmd命令道myeclipse.exe 目录,然后执行myeclipse.exe ...

  2. web全栈架构师[笔记] — 03 html5新特性

    HTML5新特性 一.geolocation PC端 精度比较低 通过IP库定位 移动端 通过GPS window.navigator.geolocation 单次 getCurrentPositio ...

  3. ArcGIS Server Rest 认证过程分析

    1. http://192.168.1.220:6080/arcgis/admin/login?redirect= Request URL: http://192.168.1.220:6080/arc ...

  4. SVN SVN合并(Merge)与拉取分支(Branch/tag)操作简介

    SVN合并(Merge)与拉取分支(Branch/tag)操作简介 合并(Merge) 例子:把对feature_branch\project_name_v3.3.7_branch的修改合并到deve ...

  5. 2018最新大厂Android面试真题

    前言 又到了金三银四的面试季,自己也不得不参与到这场战役中来,其实是从去年底就开始看,android的好机会确实不太多,但也还好,3年+的android开发经历还是有一些面试机会的,不过确实不像几年前 ...

  6. Hexo + Github 个人博客设置以及优化

    原文地址: Hexo + Github 个人博客设置以及优化 一.博客设置 分类.标签云.关于等页面 在站点目录下分别执行: hexo new page "categories" ...

  7. 常用css字体英文写法

    font-family: 'Microsoft Yahei',sans-serif; 宋体:SimSun 黑体:SimHei

  8. 启动OpenVPN失败

    启动OpenVPN失败 文:铁乐与猫 [root@yunwei_OpenVPN openvpn]# systemctl status openvpn ● openvpn.service - LSB: ...

  9. 阿里八八β阶段Scrum(2/5)

    今日进度 黄梅玲:尝试修复日程界面的不可点击问题 李嘉群:修改数据库,增加写入识别功能临时文本存入的项 张岳:信息抽取算法的编写 叶文滔:尝试侧边栏的信息调用,但因为侧边栏不是单独的活动,调用碰到了困 ...

  10. Java设计模式之十 ---- 访问者模式和中介者模式

    前言 2018年已经过去,新的一年工作已经开始,继续总结和学习Java设计模式. 在上一篇中我们学习了行为型模式的解释器模式(Interpreter Pattern)和迭代器模式(Iterator P ...