ytq鸽鸽出的题真是毒瘤

原题传送门

题目大意:

有一棵有\(n\)个点的树,求有多少方案选\(k\)个联通块使得存在一个中心点\(p\),所有\(k\)个联通块中所有点到\(p\)的距离都\(\leq L\)

我们先从部分分考虑:

算法1

\(2^{nk}\)枚举联通快判断是否可行

期望得分:8pts

代码就不给了

引理1

对于任意一个联通块,可能成为它的中心点的点组成的集合也是一个联通块。正确性显然

  • 推论

这里作为\(k\)个联通块中心点的点组成的集合是一个联通块

算法2

枚举推论中中心点组成的集合,判断其他是否满足

期望得分:16pts

代码也不给了

引理2

注意到树上联通块中,点集为\(S\),边集为\(E\),有\(|S|-|E|=1\)。正确性显然

这样我们就珂以对每个点、边单独考虑,通过容斥算出答案。设\(f(x)\)表示\(x\)控制的联通块个数,\(g(e)\)表示\(e\)两端点都控制的联通块个数,易知答案为

\[\sum_{v \in V}f(v)^k-\sum_{e \in E}g(e)^k
\]

算法3

我们考虑dp,设\(f_{i,j}\)表示\(i\)点子树中距离\(i\)不超过\(j\)且包含\(i\)的个数,\(g_{i,j}\)表示\(i\)点子树外距离\(i\)不超过\(j\)且包含\(i\)的个数,转移如下:

\[f_{i,j}=\prod_{v \in son(i)}(f_{v,j-1}+1)
\]

\[g_{i,j}=g_{fa_i,j-1}\prod_{v \in son(fa_i),v \neq i}(f_{v,j-2}+1)+1
\]

对于每个点\(i\),对答案的贡献为:

\[(f_{i,L}·g_{i,L})^k
\]

对于每条边\(e\)(设\(v\)为深度更深的点),对答案的贡献为:

\[-(f_{v,L-1}·(g_{v,L}-1))^k
\]

时间复杂度:\(O(nL)\)

期望得分:36pts

算法4:

对于\(L=n\)的测试点,第二维的限制没用了,去掉即可

时间复杂度:\(O(n)\)

期望得分:结合算法3可得48pts

算法5:

对于链的情况,珂以手推一下dp的贡献,发现就是距离,算一下即可

时间复杂度:\(O(n)\)

期望得分:结合算法4可得52pts

这是暴力52pts的做法,代码如下,subtask1是算法3,subtask2是算法4,subtask3是算法5

  1. #include <bits/stdc++.h>
  2. #define mod 998244353
  3. #define N 100005
  4. #define getchar nc
  5. using namespace std;
  6. inline char nc(){
  7. static char buf[100000],*p1=buf,*p2=buf;
  8. return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
  9. }
  10. inline int read()
  11. {
  12. register int x=0,f=1;register char ch=getchar();
  13. while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
  14. while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
  15. return x*f;
  16. }
  17. inline void write(register int x)
  18. {
  19. if(!x)putchar('0');if(x<0)x=-x,putchar('-');
  20. static int sta[20];register int tot=0;
  21. while(x)sta[tot++]=x%10,x/=10;
  22. while(tot)putchar(sta[--tot]+48);
  23. }
  24. inline int power(register int a,register int b)
  25. {
  26. int res=1;
  27. while(b)
  28. {
  29. if(b&1)
  30. res=1ll*res*a%mod;
  31. a=1ll*a*a%mod;
  32. b>>=1;
  33. }
  34. return res;
  35. }
  36. struct egde{
  37. int to,next;
  38. }e[N<<2];
  39. int head[N<<1],cnt=0;
  40. inline void add(register int u,register int v)
  41. {
  42. e[++cnt]=(egde){v,head[u]};
  43. head[u]=cnt;
  44. }
  45. int n,m,k,ans;
  46. namespace subtask1{
  47. vector<int> f[N],g[N];
  48. inline void dfs1(register int x,register int fa)
  49. {
  50. for(register int i=head[x];i;i=e[i].next)
  51. {
  52. int v=e[i].to;
  53. if(v==fa)
  54. continue;
  55. dfs1(v,x);
  56. for(register int j=1;j<=m;++j)
  57. f[x][j]=1ll*f[x][j]*(f[v][j-1]+1)%mod;
  58. }
  59. }
  60. inline void dfs2(register int x,register int fa)
  61. {
  62. static int son[N],pre[N],suf[N];
  63. int cnt=0;
  64. for(register int i=head[x];i;i=e[i].next)
  65. if(e[i].to!=fa)
  66. son[++cnt]=e[i].to;
  67. for(register int i=pre[0]=suf[cnt+1]=1;i<=m;++i)
  68. {
  69. if(i>=2)
  70. {
  71. for(register int j=1;j<=cnt;++j)
  72. pre[j]=1ll*pre[j-1]*(f[son[j]][i-2]+1)%mod;
  73. for(register int j=cnt;j>=1;--j)
  74. suf[j]=1ll*suf[j+1]*(f[son[j]][i-2]+1)%mod;
  75. }
  76. else
  77. {
  78. for(register int j=1;j<=cnt;++j)
  79. pre[j]=suf[j]=1;
  80. }
  81. for(register int j=1;j<=cnt;++j)
  82. g[son[j]][i]=(1ll*g[x][i-1]*pre[j-1]%mod*suf[j+1]+1)%mod;
  83. }
  84. for(register int i=head[x];i;i=e[i].next)
  85. {
  86. int v=e[i].to;
  87. if(v==fa)
  88. continue;
  89. ans=(ans+power(1ll*(g[v][m]-1)*f[v][m-1]%mod,k))%mod;
  90. dfs2(v,x);
  91. }
  92. }
  93. inline void solve()
  94. {
  95. for(register int i=1;i<=n;++i)
  96. f[i].resize(m+1,1),g[i].resize(m+1,1);
  97. dfs1(1,0);
  98. dfs2(1,0);
  99. ans=mod-ans;
  100. for(register int i=1;i<=n;++i)
  101. ans=(0ll+ans+power(1ll*f[i][m]*g[i][m]%mod,k))%mod;
  102. write(ans);
  103. }
  104. }
  105. namespace subtask2{
  106. int a[200005],b[200005];
  107. inline void dfs1(register int x,register int fa)
  108. {
  109. for(register int i=head[x];i;i=e[i].next)
  110. {
  111. int v=e[i].to;
  112. if(v==fa)
  113. continue;
  114. dfs1(v,x);
  115. a[x]=1ll*a[x]*(a[v]+1)%mod;
  116. }
  117. }
  118. inline void dfs2(register int x,register int fa)
  119. {
  120. static int son[200005],pre[200005],suf[200005];
  121. int cnt=0;
  122. for(register int i=head[x];i;i=e[i].next)
  123. if(e[i].to!=fa)
  124. son[++cnt]=e[i].to;
  125. pre[0]=suf[cnt+1]=1;
  126. for(register int j=1;j<=cnt;++j)
  127. pre[j]=1ll*pre[j-1]*(a[son[j]]+1)%mod;
  128. for(register int j=cnt;j>=1;--j)
  129. suf[j]=1ll*suf[j+1]*(a[son[j]]+1)%mod;
  130. for(register int j=1;j<=cnt;++j)
  131. b[son[j]]=(1ll*b[x]*pre[j-1]%mod*suf[j+1]+1)%mod;
  132. for(register int i=head[x];i;i=e[i].next)
  133. {
  134. int v=e[i].to;
  135. if(v==fa)
  136. continue;
  137. ans=(ans+power(1ll*(b[v]-1)*a[v]%mod,k))%mod;
  138. dfs2(v,x);
  139. }
  140. }
  141. inline void solve()
  142. {
  143. for(register int i=0;i<=n;++i)
  144. a[i]=b[i]=1;
  145. dfs1(1,0);
  146. dfs2(1,0);
  147. ans=mod-ans;
  148. for(register int i=1;i<=n;++i)
  149. ans=(ans+power(1ll*a[i]*b[i]%mod,k))%mod;
  150. write(ans);
  151. }
  152. }
  153. namespace subtask3{
  154. inline void solve()
  155. {
  156. for(register int i=1;i<=n;++i)
  157. {
  158. int l=max(1,i-m),r=min(n,i+m);
  159. ans=(ans+power(1ll*(i-l+1)*(r-i+1)%mod,k))%mod;
  160. }
  161. for(register int i=2;i<=n;++i)
  162. {
  163. int l=max(1,i-m),r=min(n,i+m-1);
  164. ans=(ans+mod-power(1ll*(i-l+1-1)*(r-i+1)%mod,k))%mod;
  165. }
  166. write(ans);
  167. }
  168. }
  169. int main()
  170. {
  171. n=read(),m=read(),k=read();
  172. if(n<=200000)
  173. {
  174. for(register int i=1;i<n;++i)
  175. {
  176. int u=read(),v=read();
  177. add(u,v),add(v,u);
  178. }
  179. }
  180. if(m==n&&n<=200000)
  181. subtask2::solve();
  182. else if(n<=100000)
  183. subtask1::solve();
  184. else
  185. subtask3::solve();
  186. return 0;
  187. }

算法6

发现\(f,g\)的转移珂以用长链剖分优化,套上一个可持久化数据结构,需要资瓷区间加、区间乘

时间复杂度:\(O(n\log n)\)

期望得分:结合算法5可得84pts

算法7

发现是全局加,后缀乘,这样可以像SDOI2019Day1T1 快速查询

珂以用数组线性维护,为了去掉求逆元的\(log\),我们珂以用类似于求阶乘逆元的方法\(O(n)\)预处理要用的逆元

至此,我们得到了一个\(O(n)\)的做法

期望得分:100pts

  1. #include <bits/stdc++.h>
  2. #define mod 998244353
  3. #define N 1000005
  4. #define getchar nc
  5. using namespace std;
  6. inline char nc(){
  7. static char buf[100000],*p1=buf,*p2=buf;
  8. return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
  9. }
  10. inline int read()
  11. {
  12. register int x=0,f=1;register char ch=getchar();
  13. while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
  14. while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
  15. return x*f;
  16. }
  17. inline void write(register int x)
  18. {
  19. if(!x)putchar('0');if(x<0)x=-x,putchar('-');
  20. static int sta[20];register int tot=0;
  21. while(x)sta[tot++]=x%10,x/=10;
  22. while(tot)putchar(sta[--tot]+48);
  23. }
  24. inline int power(register int a,register int b)
  25. {
  26. int res=1;
  27. while(b)
  28. {
  29. if(b&1)
  30. res=1ll*res*a%mod;
  31. a=1ll*a*a%mod;
  32. b>>=1;
  33. }
  34. return res;
  35. }
  36. struct edge{
  37. int to,next;
  38. }e[N<<1];
  39. int head[N],cnt=0;
  40. inline void add(register int u,register int v)
  41. {
  42. e[++cnt]=(edge){v,head[u]};
  43. head[u]=cnt;
  44. }
  45. int n,m,k;
  46. int dp[N],son[N],len[N],val[N],idx[N],tot,inv[N];
  47. int arr[N<<3],*pos=arr,*f[N<<1],*g[N],ans[2][N],Ans;
  48. inline void dfs1(register int x,register int fa)
  49. {
  50. dp[x]=1;
  51. for(register int i=head[x];i;i=e[i].next)
  52. {
  53. int v=e[i].to;
  54. if(v==fa)
  55. continue;
  56. dfs1(v,x);
  57. son[x]=len[v]>len[son[x]]?v:son[x];
  58. dp[x]=1ll*dp[x]*dp[v]%mod;
  59. }
  60. if(++dp[x]<mod)
  61. val[idx[x]=++tot]=dp[x];
  62. len[x]=len[son[x]]+1;
  63. }
  64. inline void init_inv()
  65. {
  66. static int pre[N];
  67. for(register int i=pre[0]=1;i<=tot;++i)
  68. pre[i]=1ll*pre[i-1]*val[i]%mod;
  69. int pre_inv=power(pre[tot],mod-2);
  70. for(register int i=tot;i;--i)
  71. inv[i]=1ll*pre[i-1]*pre_inv%mod,pre_inv=1ll*pre_inv*val[i]%mod;
  72. }
  73. struct node{
  74. int a,b,inv,pos,num;
  75. };
  76. namespace F{
  77. node tag[N<<1];
  78. vector<pair<node,vector<pair<int,int> > > >backup[N];
  79. inline int get(register int u,register int i)
  80. {
  81. int res=i<tag[u].pos?f[u][i]:tag[u].num;
  82. return (1ll*res*tag[u].a+tag[u].b)%mod;
  83. }
  84. inline void put(register int u,register int i,register int v)
  85. {
  86. f[u][i]=1ll*(v+mod-tag[u].b)*tag[u].inv%mod;
  87. }
  88. inline void merge(register int u,register int v,register int l)
  89. {
  90. node tmp=tag[u];
  91. vector<pair<int,int> >vec;
  92. for(register int i=1;i<=l;++i)
  93. {
  94. vec.push_back(make_pair(i,f[u][i]));
  95. int val=get(v,i-1);
  96. if(i==tag[u].pos)
  97. f[u][tag[u].pos++]=tag[u].num;
  98. put(u,i,1ll*get(u,i)*val%mod);
  99. }
  100. if(l<m)
  101. {
  102. int val=get(v,l);
  103. if(!val)
  104. tag[u].pos=l+1,tag[u].num=mod-1ll*tag[u].b*tag[u].inv%mod;
  105. else
  106. {
  107. int t=inv[idx[v]];
  108. vec.push_back(make_pair(0,f[u][0]));
  109. for(register int i=0;i<=l;++i)
  110. put(u,i,1ll*get(u,i)*t%mod);
  111. tag[u].a=1ll*tag[u].a*val%mod;
  112. tag[u].b=1ll*tag[u].b*val%mod;
  113. tag[u].inv=1ll*tag[u].inv*t%mod;
  114. }
  115. }
  116. if(u<=n)
  117. backup[u].push_back(make_pair(tmp,vec));
  118. }
  119. inline void dfs2(register int x,register int fa)
  120. {
  121. if(son[x])
  122. f[son[x]]=f[x]+1,dfs2(son[x],x),tag[x]=tag[son[x]];
  123. else
  124. tag[x]=(node){1,1,1,n,0};
  125. put(x,0,1);
  126. for(register int i=head[x];i;i=e[i].next)
  127. {
  128. int v=e[i].to;
  129. if(v==fa||v==son[x])
  130. continue;
  131. f[v]=pos;
  132. pos+=len[v];
  133. dfs2(v,x);
  134. merge(x,v,min(len[v]-1,m));
  135. }
  136. ans[0][x]=get(x,min(len[x]-1,m-1));
  137. ans[1][x]=get(x,min(len[x]-1,m));
  138. ++tag[x].b;
  139. }
  140. inline void rollback(register int u)
  141. {
  142. tag[u]=backup[u].back().first;
  143. for(register int i=0;i<(backup[u].back().second).size();++i)
  144. f[u][(backup[u].back().second)[i].first]=(backup[u].back().second)[i].second;
  145. backup[u].pop_back();
  146. }
  147. }
  148. namespace G{
  149. node tag[N];
  150. inline int get(register int u,register int i)
  151. {
  152. int res=i<tag[u].pos?g[u][i]:tag[u].num;
  153. return (1ll*res*tag[u].a+tag[u].b)%mod;
  154. }
  155. inline void put(register int u,register int i,register int v)
  156. {
  157. g[u][i]=1ll*(v+mod-tag[u].b)*tag[u].inv%mod;
  158. }
  159. inline void dfs3(register int x,register int fa)
  160. {
  161. if(len[x]-m-1>=0)
  162. put(x,len[x]-m-1,1);
  163. Ans=(Ans+power(1ll*ans[1][x]*get(x,len[x]-1)%mod,k))%mod;
  164. if(fa)
  165. Ans=(Ans-power(1ll*ans[0][x]*(get(x,len[x]-1)+mod-1)%mod,k)+mod)%mod;
  166. if(!son[x])
  167. return;
  168. vector<int> ch;
  169. int maxlen=0;
  170. for(register int i=head[x];i;i=e[i].next)
  171. {
  172. int v=e[i].to;
  173. if(v==fa||v==son[x])
  174. continue;
  175. ch.push_back(v);
  176. maxlen=max(maxlen,len[v]);
  177. }
  178. maxlen=min(maxlen,m);
  179. reverse(ch.begin(),ch.end());
  180. f[x+n]=pos;
  181. pos+=maxlen+1;
  182. F::tag[x+n]=(node){1,1,1,n,0};
  183. F::put(x+n,0,1);
  184. for(register int id=0;id<ch.size();++id)
  185. {
  186. int v=ch[id];
  187. F::rollback(x);
  188. g[v]=pos;
  189. pos+=len[v];
  190. for(register int i=max(len[v]-m-1,0);i<len[v];++i)
  191. {
  192. if(m-len[v]+i==-1)
  193. g[v][i]=get(x,len[son[x]]-len[v]+i);
  194. else
  195. g[v][i]=1ll*get(x,len[son[x]]-len[v]+i)*F::get(x,min(len[x]-1,m-len[v]+i))%mod*F::get(x+n,min(maxlen,m-len[v]+i))%mod;
  196. }
  197. tag[v]=(node){1,1,1,n,0};
  198. F::merge(x+n,v,min(len[v]-1,m));
  199. dfs3(v,x);
  200. }
  201. int v=son[x];
  202. g[v]=g[x];
  203. tag[v]=tag[x];
  204. for(register int i=max(len[v]-m,0);i<=len[v]+maxlen-m-1;++i)
  205. {
  206. if(tag[v].pos==i)
  207. g[v][tag[v].pos++]=tag[v].num;
  208. put(v,i,1ll*get(v,i)*F::get(x+n,m-len[v]+i)%mod);
  209. }
  210. if(maxlen<m)
  211. {
  212. int vv=1,tt=1;
  213. for(register int i=0;i<ch.size();++i)
  214. vv=1ll*vv*val[idx[ch[i]]]%mod,tt=1ll*tt*inv[idx[ch[i]]]%mod;
  215. if(!vv)
  216. tag[v].pos=len[v]+maxlen-m,tag[v].num=mod-1ll*tag[v].b*tag[v].inv%mod;
  217. else
  218. {
  219. for(register int i=max(len[v]-m-1,0);i<=len[v]+maxlen-m-1;++i)
  220. put(v,i,1ll*get(v,i)*tt%mod);
  221. tag[v].a=1ll*tag[v].a*vv%mod;
  222. tag[v].b=1ll*tag[v].b*vv%mod;
  223. tag[v].inv=1ll*tag[v].inv*tt%mod;
  224. }
  225. }
  226. ++tag[v].b;
  227. dfs3(v,x);
  228. }
  229. }
  230. int main()
  231. {
  232. n=read(),m=read(),k=read();
  233. for(register int i=1;i<n;++i)
  234. {
  235. int u=read(),v=read();
  236. add(u,v),add(v,u);
  237. }
  238. dfs1(1,0);
  239. init_inv();
  240. f[1]=pos;
  241. pos+=len[1];
  242. F::dfs2(1,0);
  243. g[1]=pos;
  244. pos+=len[1];
  245. G::tag[1]=(node){1,1,1,n,0};
  246. G::dfs3(1,0);
  247. write(Ans);
  248. return 0;
  249. }

【题解】Luogu P5291 [十二省联考2019]希望的更多相关文章

  1. luogu P5291 [十二省联考2019]希望

    luogu loj 无论最终结果将人类历史导向何处 \(\quad\)我们选择 \(\quad\quad\)\(\large{希望}\) 诶我跟你讲,这题超修咸的 下面称离连通块内每个点距离不超过\( ...

  2. 【题解】Luogu P5284 [十二省联考2019]字符串问题

    原题传送门 我用sa做的本题 (码量似乎有点大) 先对原串建sa 考虑如何建图: 从大到小枚举长度len 先将height中等于len的两个位置在并查集合并起来,将lst也合并(lst是链表) 再将长 ...

  3. 【题解】Luogu P5283 [十二省联考2019]异或粽子

    原题传送门 看见一段的异或和不难想到要做异或前缀和\(s\) 我们便将问题转化成:给定\(n\)个数,求异或值最靠前的\(k\)对之和 我们珂以建一个可持久化01trie,这样我们就珂以求出每个值\( ...

  4. 【题解】Luogu P5290 [十二省联考2019]春节十二响

    原题传送门 每个点维护一个堆,表示这个点及其子树所需的每段内存的空间 搜索时从下向上做启发式合并堆中信息,最后根节点堆中所有内存空间之和就是答案 #include <bits/stdc++.h& ...

  5. 题解 loj3050 「十二省联考 2019」骗分过样例

    CASE \(1\sim 3\) \(n\)组测试数据,每次输入一个数\(x\),求\(19^x\). 测试点\(1\),\(x=0,1,\dots n-1\),可以直接递推. 测试点\(2\)要开l ...

  6. Luogu P5285 [十二省联考2019]骗分过样例

    Preface ZJOI一轮被麻将劝退的老年选手看到这题就两眼放光,省选也有乱搞题? 然后狂肝了3~4天终于打完了,期间还补了一堆姿势 由于我压缩技术比较菜,所以用的都是非打表算法,所以一共写了5K- ...

  7. Luogu P5290 [十二省联考2019]春节十二响

    这题是最近看到的今年省选题中最良心的一道了吧 看题+想题+写题都可以在0.5h内解决,送分含义明显啊 首先理解了题意后我们很快就能发现两个点如果要被分在一段那么必须在它们的祖先处合并 首先我们考虑下二 ...

  8. Luogu P5284 [十二省联考2019]字符串问题

    好难写的字符串+数据结构问题,写+调了一下午的说 首先理解题意后我们对问题进行转化,对于每个字符串我们用一个点来代表它们,其中\(A\)类串的点权为它们的长度,\(B\)类串的权值为\(0\) 这样我 ...

  9. Luogu P5283 [十二省联考2019]异或粽子

    感觉不是很难的一题,想了0.5h左右(思路歪了,不过想了一个大常数的两只\(\log\)做法233) 然后码+调了1h,除了一个SB的数组开小外基本上也没什么坑点 先讲一个先想到的方法,我们对于这种问 ...

随机推荐

  1. SqlServer数据库之递归

    递归的实现比较简单,这里就直接贴SQL了. --简单创建一个用户表 CREATE TABLE User( UserID ,) , ParentUserID INT ) 假设这张有几千条数据,开始递归它 ...

  2. mybatis中的高级查询

    Mybatis作为一个ORM框架,肯定是支持sql高级查询的. 下面的一个案例来为大家详细讲解mybatis中的高级查询. 案例说明: 此案例的业务关系是用户,订单,订单详情与商品之间的关系. 以订单 ...

  3. 6.redis 的持久化有哪几种方式?不同的持久化机制都有什么优缺点?持久化机制具体底层是如何实现的?

    作者:中华石杉 面试题 redis 的持久化有哪几种方式?不同的持久化机制都有什么优缺点?持久化机制具体底层是如何实现的? 面试官心理分析 redis 如果仅仅只是将数据缓存在内存里面,如果 redi ...

  4. mysql中的where和having的区别

    下面以一个例子来具体的讲解: 1. where和having都可以使用的场景 1)select addtime,name from dw_users where addtime> 1500000 ...

  5. eclipse activiti 不能自动生成png图片解决方案

    1. Windows-->Preferences 2. Activiti-->Save Actions-->勾选 Create process definition ... --&g ...

  6. ArmIE的安装

    参考:https://developer.arm.com/tools-and-software/server-and-hpc/arm-architecture-tools/arm-instructio ...

  7. Codeforces J. Sagheer and Nubian Market(二分枚举)

    题目描述: Sagheer and Nubian Market time limit per test 2 seconds memory limit per test 256 megabytes in ...

  8. NLP中的预训练语言模型(一)—— ERNIE们和BERT-wwm

    随着bert在NLP各种任务上取得骄人的战绩,预训练模型在这不到一年的时间内得到了很大的发展,本系列的文章主要是简单回顾下在bert之后有哪些比较有名的预训练模型,这一期先介绍几个国内开源的预训练模型 ...

  9. uboot向kernel的传参机制——bootm与tags

    http://blog.csdn.net/skyflying2012/article/details/35787971 最近阅读代码学习了uboot boot kernel的过程以及uboot如何传参 ...

  10. flask实战-个人博客-编写博客前台

    编写博客前台 博客前台需要开放给所有用户,这里包括显示文章列表.博客信息.文章内容和评论等功能功能. 分页显示文章列表 为了在主页显示文章列表,我们要先在渲染主页模板的index视图的数据库中获取所有 ...