题目

观察当k固定时答案是什么。先假设每个节点对答案的贡献都是\(\binom{n}{k}\),然后再减掉某个点没有贡献的选点方案数。对于一个节点i,它没有贡献的方案数显然就是所有k个节点都选在i连出去的某一个子树内的方案数。枚举节点i,把i连出去的每一个子树的size都加入一个序列c,则答案为\(\binom{n}{k}\cdot n-\sum_{i=0}^{|c|-1}\binom{c_i}{k}\)。

考虑\(k=1\cdots n\)的情况:

\(ans_k=\binom{n}{k}\cdot n-\sum_{i=0}^{|c|-1}\binom{c_i}{k}=\binom{n}{k}\cdot n-\sum_{i=0}^{|c|-1}\binom{c_i}{c_i-k}=\binom{n}{k}\cdot n-\sum_{i=0}^{|c|-1}\frac{c_i!}{k!(c_i-k)!}\)

\(-ans_k k!+\binom nk\cdot n\cdot k!=\sum_{i=0}^{|c|-1}\frac{c_i!}{(c_i-k)!}\)

统计每种\(c_i\)的出现次数后,右边就变成了一个减法卷积的形式,一遍NTT即可。需要注意题目中的模数的原根是5.时间复杂度\(O(nlogn)\)。

点击查看代码
  1. #include <bits/stdc++.h>
  2. #define rep(i,n) for(int i=0;i<n;++i)
  3. #define repn(i,n) for(int i=1;i<=n;++i)
  4. #define LL long long
  5. #define pii pair <LL,LL>
  6. #define fi first
  7. #define se second
  8. #define mpr make_pair
  9. #define pb push_back
  10. using namespace std;
  11. const LL MOD=924844033;
  12. LL qpow(LL x,LL a)
  13. {
  14. LL res=x,ret=1;
  15. while(a>0)
  16. {
  17. if((a&1)==1) ret=ret*res%MOD;
  18. a>>=1;
  19. res=res*res%MOD;
  20. }
  21. return ret;
  22. }
  23. namespace poly
  24. {
  25. vector <LL> rev;
  26. void ntt(vector <LL> &a,LL G)
  27. {
  28. LL nn=a.size(),gn,g,x,y;vector <LL> tmp=a;
  29. rep(i,nn) a[i]=tmp[rev[i]];
  30. for(int len=1;len<nn;len<<=1)
  31. {
  32. gn=qpow(G,(MOD-1)/(len<<1));
  33. for(int i=0;i<nn;i+=(len<<1))
  34. {
  35. g=1;
  36. for(int j=i;j<i+len;++j,(g*=gn)%=MOD)
  37. {
  38. x=a[j];y=a[j+len]*g%MOD;
  39. a[j]=(x+y)%MOD;a[j+len]=(x-y+MOD)%MOD;
  40. }
  41. }
  42. }
  43. }
  44. vector <LL> convolution(vector <LL> a,vector <LL> b,LL G)
  45. {
  46. LL nn=1,bt=0,sv=a.size()+b.size()-1;while(nn<a.size()+b.size()-1) nn<<=1LL,++bt;
  47. while(a.size()<nn) a.pb(0);while(b.size()<nn) b.pb(0);
  48. rev.clear();
  49. rep(i,nn)
  50. {
  51. rev.pb(0);
  52. rev[i]=(rev[i>>1]>>1)|((i&1)<<(bt-1));
  53. }
  54. ntt(a,G);ntt(b,G);
  55. rep(i,nn) (a[i]*=b[i])%=MOD;
  56. ntt(a,qpow(G,MOD-2));
  57. while(a.size()>sv) a.pop_back();
  58. LL inv=qpow(nn,MOD-2);
  59. rep(i,a.size()) (a[i]*=inv)%=MOD;
  60. return a;
  61. }
  62. vector <LL> inverse(vector <LL> a,LL G)
  63. {
  64. if(a.size()==1) return vector <LL>{qpow(a[0],MOD-2)};
  65. vector <LL> aa=a;while(aa.size()>(a.size()+1)>>1) aa.pop_back();
  66. vector <LL> bb=inverse(aa,G);
  67. LL nn=1,bt=0,sv=a.size();while(nn<a.size()*2) nn<<=1LL,++bt;
  68. while(a.size()<nn) a.pb(0);while(bb.size()<nn) bb.pb(0);
  69. rev.clear();
  70. rep(i,nn)
  71. {
  72. rev.pb(0);
  73. rev[i]=(rev[i>>1]>>1)|((i&1)<<(bt-1));
  74. }
  75. ntt(a,G);ntt(bb,G);
  76. rep(i,nn) a[i]=(2LL-a[i]*bb[i]%MOD+MOD)*bb[i]%MOD;
  77. ntt(a,qpow(G,MOD-2));
  78. while(a.size()>sv) a.pop_back();
  79. LL inv=qpow(nn,MOD-2);
  80. rep(i,a.size()) (a[i]*=inv)%=MOD;
  81. return a;
  82. }
  83. vector <LL> sqrt1(vector <LL> a,LL G)//常数项为1
  84. {
  85. if(a.size()==1) return vector <LL>{1};
  86. vector <LL> aa=a;while(aa.size()>(a.size()+1)>>1) aa.pop_back();
  87. vector <LL> bb=sqrt1(aa,G);while(bb.size()<a.size()) bb.pb(0);
  88. vector <LL> bbb=inverse(bb,G);
  89. LL nn=1,bt=0,sv=a.size();while(nn<a.size()*2) nn<<=1LL,++bt;
  90. while(a.size()<nn) a.pb(0);while(bb.size()<nn) bb.pb(0);while(bbb.size()<nn) bbb.pb(0);
  91. rev.clear();
  92. rep(i,nn)
  93. {
  94. rev.pb(0);
  95. rev[i]=(rev[i>>1]>>1)|((i&1)<<(bt-1));
  96. }
  97. LL mul=qpow(2,MOD-2);
  98. ntt(a,G);ntt(bb,G);ntt(bbb,G);
  99. rep(i,nn) a[i]=mul*(bb[i]+bbb[i]*a[i]%MOD)%MOD;
  100. ntt(a,qpow(G,MOD-2));
  101. while(a.size()>sv) a.pop_back();
  102. LL inv=qpow(nn,MOD-2);
  103. rep(i,a.size()) (a[i]*=inv)%=MOD;
  104. return a;
  105. }
  106. }
  107. LL n,sz[200010],fac[200010],inv[200010],ans[200010];
  108. vector <LL> g[200010],A,B,C;
  109. LL CC(LL nn,LL mm){return fac[nn]*inv[mm]%MOD*inv[nn-mm]%MOD;}
  110. void dfs(LL pos,LL par)
  111. {
  112. sz[pos]=1;
  113. rep(i,g[pos].size()) if(g[pos][i]!=par)
  114. {
  115. dfs(g[pos][i],pos);
  116. sz[pos]+=sz[g[pos][i]];
  117. ++A[sz[g[pos][i]]];
  118. }
  119. if(pos!=1) ++A[n-sz[pos]];
  120. }
  121. int main()
  122. {
  123. fac[0]=1;repn(i,200005) fac[i]=fac[i-1]*(LL)i%MOD;
  124. rep(i,200003) inv[i]=qpow(fac[i],MOD-2);
  125. cin>>n;
  126. LL x,y;
  127. rep(i,n-1)
  128. {
  129. scanf("%lld%lld",&x,&y);
  130. g[x].pb(y);g[y].pb(x);
  131. }
  132. rep(i,n) A.pb(0);
  133. dfs(1,0);
  134. rep(i,n) (A[i]*=fac[i])%=MOD;
  135. rep(i,n) B.pb(inv[i]);
  136. reverse(B.begin(),B.end());
  137. C=poly::convolution(A,B,5);
  138. repn(i,n)
  139. {
  140. ans[i]=CC(n,i)*n%MOD;
  141. (ans[i]+=MOD-(i+n-1>=C.size() ? 0LL:C[i+n-1])*inv[i]%MOD)%=MOD;
  142. }
  143. repn(i,n) printf("%lld\n",ans[i]);
  144. return 0;
  145. }

[题解] Atcoder AGC 005 F Many Easy Problems NTT,组合数学的更多相关文章

  1. AtcoderGrandContest 005 F. Many Easy Problems

    $ >AtcoderGrandContest \space 005 F.  Many Easy Problems<$ 题目大意 : 有一棵大小为 \(n\) 的树,对于每一个 \(k \i ...

  2. 【AtCoder】AGC005 F - Many Easy Problems 排列组合+NTT

    [题目]F - Many Easy Problems [题意]给定n个点的树,定义S为大小为k的点集,则f(S)为最小的包含点集S的连通块大小,求k=1~n时的所有点集f(S)的和取模92484403 ...

  3. 【AGC 005F】Many Easy Problems

    Description One day, Takahashi was given the following problem from Aoki: You are given a tree with ...

  4. AtCoder Grand Contest 005F - Many Easy Problems

    $n \leq 200000$的树,从树上选$k$个点的一个方案会对$Ans_k$产生大小为“最小的包括这$k$个点的连通块大小”的贡献.求每个$Ans_k$.膜924844033. 看每个点对$An ...

  5. 【AGC005F】Many Easy Problems (NTT)

    Description ​ 给你一棵\(~n~\)个点的树和一个整数\(~k~\).设为\(~S~\)为树上某些点的集合,定义\(~f(S)~\)为最小的包含\(~S~\)的联通子图的大小.\(~n~ ...

  6. 【AtCoder】AGC005F - Many Easy Problems

    题解 我们把一个点的贡献转化为一条边的贡献,因为边的数量是点的数量-1,最后再加上选点方案数\(\binom{n}{k}\)即可 一条边的贡献是\(\binom{n}{k} - \binom{a}{k ...

  7. 解题:AT2064 Many Easy Problems&EXNR #1 T3 两开花

    题面 两道题比较像,放在一起写了,后者可以看成前者的加强版 (sto ztb orz) 先看AT那道题 考虑计算每个点的贡献,用容斥计算:每个点没有贡献当且仅当选的所有点都在以他为根时的一个子节点的子 ...

  8. 【CodeForces】913 D. Too Easy Problems

    [题目]D. Too Easy Problems [题意]给定n个问题和总时限T,每个问题给定时间ti和限制ai,当解决的问题数k<=ai时问题有效,求在时限T内选择一些问题解决的最大有效问题数 ...

  9. [atcoder contest 010] F - Tree Game

    [atcoder contest 010] F - Tree Game Time limit : 2sec / Memory limit : 256MB Score : 1600 points Pro ...

随机推荐

  1. js基础学习-正则表达式

    正则表达式用于对字符串模式匹配及检索替换,是对字符串执行模式匹配的强大工具. 定义的方法: var patt = new RegExp(pattern, modifiers) // var patt ...

  2. 2022-7-19 第五组 pan小堂 封装和 this

    this关键字 this关键字由来和使用: A:this:代表所在类的对象引用方法被哪个对象调用,this就代表那个对象 B:什么时候使用this呢 ? 局部变量和成员变量重名 set 和 get 方 ...

  3. python 日志类

    简介 在所有项目中必不可少的一定是日志记录系统,python为我们提供了一个比较方便的日志模块logging,通常,我们都会基于此模块编写一个日志记录类,方便将项目中的日志记录到文件中. loggin ...

  4. 如何让照片中的人物笑起来?HMS Core视频编辑服务一键微笑功能,让人物笑容更自然

    最近一键"露齿笑"席卷全网,无论是短视频用户还是社交App用户都在使用这项黑科技.当三两好友聚会拍集体照留念时,为了处理个别人的表情"瑕疵",让大家都尽量保持微 ...

  5. java实现wordCount的map

    打开IDEA,File--new --Project,新建一个项目 我们已经安装好了maven,不用白不用 这里不要选用骨架,Next.在写上Groupid,Next. 写上项目名称,finish.o ...

  6. appache ab测试高并发

    ab使用范例: 要执行 1000 次的 connection, 20 次的 concurrent (并行, 同时): 语法: ab -n 1000 -c 20 http://localhost/ind ...

  7. 内网渗透之Windows认证(二)

    title: 内网渗透之Windows认证(二) categories: 内网渗透 id: 6 key: 域渗透基础 description: Windows认证协议 abbrlink: d6b7 d ...

  8. Java开发学习(二十二)----Spring事务属性、事务传播行为

    一.事务配置 上面这些属性都可以在@Transactional注解的参数上进行设置. readOnly:true只读事务,false读写事务,增删改要设为false,查询设为true. timeout ...

  9. eplan中数据库运行提速

    access,sql,是指部件库的存储方式,eplan支持两种方式即Microsoft Office access,Microsoft SQL Server,可以通过这两种方式打开部件库,如果要打开数 ...

  10. 搞定面试官 - 可以介绍一下在 MySQL 中你平时是怎么使用 COUNT() 的嘛?

    大家好,我是程序员啊粥. 相信在大家的工作中,有很多的功能都需要用到 count(*) 来统计表中的数据行数.同时,对于一些大数据的表,用 count 都是瑟瑟发抖,往往会结合缓存等进行处理. 那么, ...