ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Atcoder 241

2022-03-05 17:34:18  阅读:188  来源: 互联网

标签:Atcoder le frac ix int i64 241 prod


Atcoder 241

\(Ex. Card Deck Score\)

题意

给定\(N\)种物品,每种物品价值为\(A_i\),个数为\(B_i\)。现在要选取\(W\)个物品,设第\(i\)种物品选了\(K_i\)个,那么一种选法的总价值就是\(\prod_{i=1}^nA_i^{k_i}\),现在要你求所有方案的总价值和。答案对\(998244353\)取模

\(1\le N\le 16\) \(1\le W\le 10^{18}\) \(1\le A_i\le 998244353\) \(1\le B_i\le 10^{17}\)

保证\(A_i\)两两互不相等。

Sol

容易写出生成函数为\(F(x)=\prod_{i=1}^n\sum_{j=0}^{B_i}(A_ix)^j=\prod_{i=1}^n\frac{1-(A_ix)^{B_i+1}}{1-A_ix}\)

由于\(N\)最大为\(16\),所以分子可以在\(O(2^n)\)内求出所有项的系数,由于我们需要的是\([x^W]F(x)\),但分式不好计算,考虑乘积项。

考虑部分分式分解:\(\frac{1}{\prod_{i=1}^n(1-A_ix)}=\frac{c_1}{1-A_1x}+\frac{c_2}{1-A_2x}+...+\frac{1}{1-A_nx}\)

设当前求系数\(c_j\),那么将上面的式子变形为\(\frac{1}{\prod_{i=1\ and \ i!=j}^n(1-A_ix)}=\frac{c_1(1-A_jx)}{1-A_1x}+\frac{c_2(1-A_jx)}{1-A_2x}+...c_j+...+\frac{c_n(1-A_jx)}{1-A_nx}\)

取\(x=A_j^{-1}\),在模\(998244353\)意义下,\(1-A_jA_j^{-1}=0\)。那么上式变为\(c_j=\frac{1}{\prod_{i=1\ and \ i!=j}^n(1-A_iA_j^{-1})}\)

又\(\frac{c_i}{1-A_ix}=c_i\sum_{j=0}^{\infty}(A_ix)^j\),用级数展开。

则\(F(x)=\prod_{i=1}^n\frac{1-(A_ix)^{B_i+1}}{1-A_ix}=\prod_{i=1}^n(1-(A_ix)^{B_i+1})\sum_{i=1}^nc_i\sum_{j=0}^{\infty}(A_ix)^j\)

#include <bits/stdc++.h>
using namespace std;
constexpr int P = 998244353;
using i64 = long long;
i64 power(i64 a, i64 b) {
    i64 res = 1LL;
    for (; b; b /= 2, a = a*a%P) {
        if (b % 2) {
            res =res*a%P;
        }
    }
    return res;
}

int main()
{
   ios::sync_with_stdio(false);
   cin.tie(nullptr);
   int n;
   i64 m;
   cin>>n>>m;
   vector<i64>A(n),B(n),p(1<<n),coef(1<<n);
   coef[0]=1LL;
   for(int i=0;i<n;i++)
   {
     cin>>A[i]>>B[i];
     B[i]++;
     i64 x=(-power(A[i],B[i])+P)%P;
     for(int j=0;j<1<<i;j++)
        coef[(1<<i)|j]=coef[j]*x%P,
        p[(1<<i)|j]=p[j]+B[i];
   }

   vector<i64>c(n);
   for(int i=0;i<n;i++)
   {
       i64 x=power(A[i],P-2);
       c[i]=1LL;
       for(int j=0;j<n;j++)
        if(j!=i) c[i]=c[i]*(1-A[j]*x%P+P)%P;
        c[i]=power(c[i],P-2); 
   }
   //for(int i=0;i<n;i++) cout<<c[i]<<" ";
   i64 res=0;
   for(int s=0;s<(1<<n);s++)
   {
      if(p[s]>m) continue;
      //cout<<p[s]<<'\n';
      i64 x=0;
      for(int i=0;i<n;i++)
        x=(x+power(A[i],m-p[s])*c[i]%P)%P;
    
      res=(res+x*coef[s]%P)%P;
   }
   cout<<res<<'\n';
   return 0;
   
}

待更

标签:Atcoder,le,frac,ix,int,i64,241,prod
来源: https://www.cnblogs.com/Arashimu0x7f/p/15968702.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有