用户工具

站点工具


2020-2021:teams:wangzai_milk:weekly6

差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

两侧同时换到之前的修订记录 前一修订版
后一修订版
前一修订版
2020-2021:teams:wangzai_milk:weekly6 [2020/06/09 11:38]
wzx27
2020-2021:teams:wangzai_milk:weekly6 [2020/07/01 13:03] (当前版本)
zars19 [Zars19]
行 1: 行 1:
-====== 2020.06.01-2020.06.07 周报 ======+====== 2020.06.08-2020.06.14 周报 ======
  
 ===== 团队训练 ===== ===== 团队训练 =====
 +2020.06.14 [[https://​codeforces.com/​gym/​101611|2017-2018 ACM-ICPC, NEERC, Moscow Subregional Contest]] ''​prob:​6:​6:​10''​ ''​rnk:​124/?''​
  
 +[[20200614比赛记录]]
 ===== _wzx27 ===== ===== _wzx27 =====
  
 === 1.指数生成函数 === === 1.指数生成函数 ===
-== 1.1 基本计数问题 == 
 常用于解决一类多重集合计数的问题 常用于解决一类多重集合计数的问题
  
行 41: 行 42:
 $$ $$
  
-然后暴力 $O(c^2logn)$ 就可以每一对 $(i,j$ 对 $\frac {x^n}{n!}$ 的系数的贡献 $(-1)^{m-i}{m \choose i}{c-m \choose j}(2i+2j-c)^n$。+然后暴力 $O(c^2logn)$ 就可以每一对 $(i,j)$ 对 $\frac {x^n}{n!}$ 的系数的贡献 $(-1)^{m-i}{m \choose i}{c-m \choose j}(2i+2j-c)^n$。
  
 <hidden code> <hidden code>
行 86: 行 87:
         cout<<​setprecision(3)<<​ans<<​endl;​         cout<<​setprecision(3)<<​ans<<​endl;​
     }     }
 +    return 0;
 +}
 +</​code>​
 +</​hidden>​
 +
 +=== 2.生成函数与多项式 ===
 +
 +生成函数没那么好求的时候就要用多项式全家桶
 +
 +[[https://​www.luogu.com.cn/​problem/​P4389|P4389付公主的背包]]
 +
 +$n$ 种无限个物品,每个物品体积为 $v_i$,求恰好装下体积为 $1~m$ 的种数。
 +
 +数据范围:$n,​m \le 1e5$
 +
 +这种题也算是生成函数的经典应用
 +
 +首先得到生成函数:$f(x)=\prod _{i=1}^n \frac 1{1-x^{v_i}}$
 +
 +两边取对数得
 +$$
 +\begin{aligned}
 +lnf(x) =&​\sum_{i=1}^n\sum_{j=0}^\infty \frac {x^{j\cdot v_i}}j \\
 +=&​\sum_{k=0}^m \sum _{v_i|k} \frac {v_i}k x^k \pmod{x^{m+1}}
 +\end{aligned}
 +$$
 +
 +$O(nlogn)$预处理出 $k$ 的所有因子,然后多项式 $\text{Exp} $求 $e^{lnf(x)}$ 即可。
 +<hidden code>
 +<code cpp>
 +#​include<​bits/​stdc++.h>​
 +#define ll long long
 +#define pii_ pair<​int,​int>​
 +#define mp_ make_pair
 +#define pb push_back
 +#define fi first
 +#define se second
 +#define rep(i,a,b) for(int i=(a);​i<​=(b);​i++)
 +#define per(i,a,b) for(int i=(a);​i>​=(b);​i--)
 +#define show1(a) cout<<#​a<<"​ = "<<​a<<​endl
 +#define show2(a,b) cout<<#​a<<"​ = "<<​a<<";​ "<<#​b<<"​ = "<<​b<<​endl
 +using namespace std;
 +const ll INF = 1LL<<​60;​
 +const int inf = 1<<​30;​
 +const int maxn = 4e5+5;
 +const ll M = 998244353;
 +inline void fastio() {ios::​sync_with_stdio(false);​cin.tie(0);​cout.tie(0);​}
 +ll qpow(ll a,ll b) {ll s=1;​while(b){if(b&​1)s=(s*a)%M;​a=(a*a)%M;​b>>​=1;​}return s; }
 +int n,​m,​cnt[maxn],​r[maxn];​
 +ll A[maxn],​B[maxn],​tmp[maxn],​t1[maxn],​t2[maxn],​t3[maxn];​
 +vector<​int>​ g[maxn];
 +void init()
 +{
 +    int n = 1e5;
 +    rep(i,1,n){
 +        for(int j=i;​j<​=n;​j+=i) g[j].pb(i);
 +    }
 +}
 +void add(ll &x,ll y)
 +{
 +    x+=y;​if(x<​0) x+=M;​if(x>​M) x-=M;
 +}
 +void NTT(ll a[],int lim,int type)
 +{
 +    rep(i,​0,​lim-1) if(i<​r[i]) swap(a[i],​a[r[i]]);​
 +    for(int mid=1;​mid<​lim;​mid<<​=1){
 +        ll wn = qpow(3,​(M-1)/​mid/​2);​
 +        if(type==-1) wn = qpow(wn,​M-2);​
 +        for(int R=mid<<​1,​j=0;​j<​lim;​j+=R){
 +            ll w = 1;
 +            for(int k=0;​k<​mid;​k++,​w=w*wn%M){
 +                ll x=a[j+k],​y=w*a[j+mid+k]%M;​
 +                a[j+k] = (x+y)%M;
 +                a[j+mid+k] = (x-y+M)%M;
 +            }
 +        }
 +    }
 +    if(type==-1){
 +        ll inv = qpow(lim,​M-2);​
 +        rep(i,​0,​lim) a[i]=a[i]*inv%M;​
 +    }
 +}
 +void PolyMul(ll a[],ll b[],int n,int m)
 +{
 +    int lim=1,l=0;
 +    while(lim<​=n+m) lim<<​=1,​l++;​
 +    rep(i,​1,​lim) r[i] = (r[i>>​1]>>​1) | ((i&​1)<<​(l-1));​
 +    NTT(a,​lim,​1);​NTT(b,​lim,​1);​
 +    rep(i,​0,​lim) a[i] = a[i]*b[i]%M;​
 +    NTT(a,​lim,​-1);​
 +}
 +void PolyInv(int n,ll a[],ll b[])
 +{
 +    if(n==1) {b[0]=qpow(a[0],​M-2);​return ;}
 +    PolyInv((n+1)>>​1,​a,​b);​
 +    int lim=1,l=0;
 +    while(lim<​2*n) lim<<​=1,​l++;​
 +    rep(i,​1,​lim-1) r[i] = (r[i>>​1]>>​1) | ((i&​1)<<​(l-1));​
 +    rep(i,​0,​n-1) tmp[i] = a[i];
 +    rep(i,​n,​lim) tmp[i] = 0;
 +    NTT(tmp,​lim,​1);​NTT(b,​lim,​1);​
 +    rep(i,​0,​lim){
 +        b[i] = (2-tmp[i]*b[i]%M+M)%M*b[i]%M;​
 +    }
 +    NTT(b,​lim,​-1);​
 +    rep(i,​n,​lim) b[i]=0;
 +}
 +void PolyDf(int n,ll a[],ll b[])
 +{
 +    rep(i,0,n) b[i] = a[i+1]*(i+1)%M;​
 +}
 +void PolyItg(int n,ll a[],ll b[])
 +{
 +    rep(i,1,n) b[i] = a[i-1]*qpow(i,​M-2)%M;​b[0]=0;​
 +}
 +void PolyLn(int n,ll a[],ll b[])
 +{
 +    PolyDf(n,​a,​t1);​
 +    PolyInv(n,​a,​t2);​
 +    PolyMul(t1,​t2,​n,​n);​
 +    PolyItg(n,​t1,​b);​
 +}
 +void PolyExp(int n,ll a[],ll b[])
 +{
 +    if(n==1) {b[0]=1;​return ;}
 +    PolyExp((n+1)>>​1,​a,​b);​
 +    int lim=1,l=0;
 +    while(lim<​2*n) lim<<​=1,​l++;​
 +    rep(i,​0,​lim) t1[i]=t2[i]=0;​
 +    PolyLn(n,​b,​t3);​
 +    rep(i,​1,​lim) r[i] = (r[i>>​1]>>​1) | ((i&​1)<<​(l-1));​
 +    rep(i,​1,​n-1) t3[i] = (a[i]-t3[i]+M)%M;​
 +    t3[0] = (1+a[0]-t3[0]+M)%M;​
 +    rep(i,​n,​lim) b[i]=t3[i]=0;​
 +    NTT(t3,​lim,​1);​NTT(b,​lim,​1);​
 +    rep(i,​0,​lim) b[i] = b[i]*t3[i]%M;​
 +    NTT(b,​lim,​-1);​
 +    rep(i,​n,​lim) b[i] = 0;
 +}
 +int main()
 +{
 +    fastio();
 +    init();
 +    cin>>​n>>​m;​
 +    int x;
 +    rep(i,1,n) {cin>>​x;​cnt[x]++;​}
 +    rep(i,0,m){
 +        ll inv = qpow(i,​M-2);​
 +        for(int x:g[i]) if(cnt[x]) add(A[i],​cnt[x]*x%M*inv%M);​
 +    }
 +    PolyExp(m+1,​A,​B);​
 +    rep(i,1,m) cout<<​B[i]<<​endl;​
     return 0;     return 0;
 } }
行 92: 行 245:
  
 ===== Infinity37 ===== ===== Infinity37 =====
 +[[20200614比赛记录#​d_decoding_of_varints|D.Decoding of Varints]]
  
 +[[20200614比赛记录#​h_hilarious_cooking|H.Hilarious Cooking]]
 ===== Zars19 ===== ===== Zars19 =====
  
 +==== 题目 ====
 +
 +[[20200614比赛记录#​C.Carpet]]
 ===== 本周推荐 ===== ===== 本周推荐 =====
2020-2021/teams/wangzai_milk/weekly6.1591673936.txt.gz · 最后更改: 2020/06/09 11:38 由 wzx27