【题解】数字组合(NTT+组合 滑稽)

今天实践一下谢总讲的宰牛刀233,滑稽。



\((1+x)(1+x)(1+x)\)的\(x^2\)系数就代表了有三个一快钱硬币构成的两块钱的方案数量。

很好理解,毕竟拆括号这种东西本身就有组合意义。

那么假设面值\(i\)有\(a_i\)个,那么最终的答案是

\[G(x)=\prod_{i=1}^{1000} (1+{a_i\choose 1}x+{a_i\choose 2}x^2\dots)
\]

的\(x^m\)项系数

直接NTT即可。

//@winlere
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm> using namespace std; typedef long long ll;
inline int qr(){
register int ret=0,f=0;
register char c=getchar();
while(c<48||c>57)f|=c==45,c=getchar();
while(c>=48&&c<=57) ret=ret*10+c-48,c=getchar();
return f?-ret:ret;
}
int la,lb;
const int maxn=1<<17|1;
int a[maxn],b[maxn];
const int mod=998244353;
namespace poly{ inline int Pow(int base,const int&p){
register int ret=1;
for(register int t=p;t;t>>=1,base=1ll*base*base%mod)
if(t&1) ret=1ll*ret*base%mod;
return ret;
} const int g=3;
const int gi=Pow(g,mod-2); int A[maxn],B[maxn],r[maxn];
int savlen=-1;
inline void getr(const int&len){
if(len==savlen)return;
savlen=len;
int cnt=0;
for(register int t=1;t<len;t=t<<1)++cnt;
for(register int t=0;t<len;++t)
r[t]=r[t>>1]>>1|(t&1)<<cnt>>1;
} inline int getlen(const int&len){
register int ret;
for(ret=1;ret<len;ret<<=1);
return ret;
} inline void NTT(int*a,const int&len,const int&tag){
getr(len);
for(register int t=0;t<len;++t)
if(r[t]>t)swap(a[t],a[r[t]]);
int *a0,*a1,s;
if(s=g,tag!=1)s=gi;
for(register int t=1,wn;t<len;t<<=1){
wn=Pow(s,(mod-1)/(t<<1));
for(register int i=0;i<len;i+=t<<1){
a1=(a0=a+i)+t;
for(register int k=0,w=1,temp;k<t;++k,++a0,++a1,w=1ll*w*wn%mod){
temp=1ll**a1*w%mod;
*a1=(*a0-temp)%mod;
*a0=(*a0+temp)%mod;
if(*a1<0)*a1+=mod;
}
}
}
if(tag!=1) for(register int t=0,inv=Pow(len,mod-2);t<len;++t)
a[t]=1ll*a[t]*inv%mod;
} void inv(int*a,int*b,const int&len){
if(len==1){b[0]=Pow(a[0],mod-2);return;}
inv(a,b,len>>1);
for(register int t=0;t<len;++t) A[t]=a[t],B[t]=b[t];
NTT(A,len<<1,1);NTT(B,len<<1,1);
for(register int t=0,ed=len<<1;t<ed;++t) A[t]=1ll*A[t]*B[t]%mod*1ll*B[t]%mod;
NTT(A,len<<1,-1);
for(register int t=0;t<len;++t) b[t]=((b[t]+b[t])%mod+mod-A[t])%mod;
} void INV(int*a,int*b,const int&len){
inv(a,b,getlen(len));
} inline void MLP(int*a,int*b,int*c,const int&len1,const int&len2){
int k=getlen(len1+len2+2);
NTT(a,k,1);NTT(b,k,1);
for(register int t=0;t<=k;++t) c[t]=1ll*a[t]*b[t]%mod;
NTT(c,k,-1);
}
} ll jc[501],v[501];
int buk[1001]; using namespace poly;
inline ll c(const int&n,const int&m){
if(n<m)return 0;
return jc[n]*v[m]%mod*v[n-m]%mod;
} int main(){
jc[0]=v[0]=1;
for(register int t=1;t<=500;++t){
jc[t]=jc[t-1]*t%mod;
v[t]=Pow(jc[t],mod-2);
}
int n=qr(),m=qr();
a[0]=1;
for(register int t=1;t<=n;++t) ++buk[qr()];
for(register int t=1;t<=1000;++t){
if(!buk[t])continue;
if(t>m)break;
memset(b,0,sizeof b);
b[0]=1;
for(register int i=1;1ll*t*i<=m&&i<=buk[t];++i)
b[i*t]=c(buk[t],i),lb=i*t;
MLP(a,b,a,la,lb);
la+=lb;
if(la>m+1){
for(register int t=m+1;t<=la;++t)
a[t]=0;
la=m;
}
}
cout<<a[m]<<endl;
return 0;
}

可还行...

【题解】数字组合(NTT+组合 滑稽)的更多相关文章

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

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

  2. 【题解】【排列组合】【回溯】【Leetcode】Gray Code

    The gray code is a binary numeral system where two successive values differ in only one bit. Given a ...

  3. Scheme实现数字电路仿真(1)——组合电路

    EDA是个很大的话题,本系列只针对其中一小部分,数字电路的仿真,叙述一点概念性的东西,并不会过于深入,这方面的内容实则是无底洞.本系列并不是真的要做EDA,按照SICP里的相关内容,采用Lisp的方言 ...

  4. Leetcode刷题笔记(Python 找出所有相加之和为n的k个组合,组合中只允许含有1-9的正整数,并且每种组合中不存在重复的数字。)

    eg:输入:k=3,n=9 输出: [[1,2,6],[1,3,5],[2,3,4]] 输入:k=2,n=5 输出:[[1,4][2,3]] #!/usr/bin/env python # -*- c ...

  5. 【题解】【排列组合】【回溯】【Leetcode】Generate Parentheses

    Given n pairs of parentheses, write a function to generate all combinations of well-formed parenthes ...

  6. 【题解】【排列组合】【素数】【Leetcode】Unique Paths

    A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below). The ...

  7. 获得N位数字字母随机组合

    import string import random def get_rand(n): allw = string.letters+string.digits r = [] for i in ran ...

  8. JVM垃圾收集器组合--各种组合对应的虚拟机参数实践

    前言 相信很多人都看过下面这张图,(来自<深入理解Java虚拟机:JVM高级特性与最佳实践>) 在学完几种垃圾收集器类型及组合后,打算看看实际中程序用到的垃圾收集器. 但是在jconsol ...

  9. 剑指offer-拓展训练-字符的所有组合-全组合

    /* 题目: 给定不含重复字符字符串的全组合. */ /* 思路: 递归法. 例给定abc,输出的组合长度为1,2,3. 对于长度为2的组合,分选择a(ab,ac)和不选择a的情况(bc). 选择a, ...

随机推荐

  1. NBNS扫描工具nbtscan-unixwiz

    NBNS扫描工具nbtscan-unixwiz NBNS是NetBIOS Name Service的缩写,表示NetBIOS名称解析服务.NETBIOS是一种网络协议,用于实现消息通信和资源共享.利用 ...

  2. bzoj 5092: [Lydsy1711月赛]分割序列

    5092: [Lydsy1711月赛]分割序列 Time Limit: 5 Sec  Memory Limit: 256 MBSubmit: 219  Solved: 100[Submit][Stat ...

  3. 2016.7.12 在navicat中用sql语句建表

    参考资料: http://jingyan.baidu.com/article/f0e83a25a8c4b022e5910116.html 即新建query,然后run. (1)点击要新建表的位置,选择 ...

  4. AutoIt3常见问题解答

    Q1 如何调试脚本? MsgBox(0,"测试",$var) ConsoleWrite("var=" & $var & @CRLF)   Q2 ...

  5. 谈论程序中的token

    -> //指针,一旦符号分开就会成以下两个意思,我们一定要注意符号 - //减号 > //大与 int a,big; if(x>big) big = x; C语言以及一些其它语言会自 ...

  6. 【Excle数据透视】如何在数据透视表字段列表中显示更多的字段

    创建完数据透视表之后,由于字段太多,在列表中没有完全显示 解决方案 通过"字段节和区域节并排"功能来显示更多字段 修改后结果 字段已经完全显示出来了! "字段节和区域节层 ...

  7. 为什么我们有时不用配置java环境变量?

    答案都在这个图中 完毕,如果还不懂请自行查询注册表相关内容学习.

  8. ORA-02050故障诊断一例

    http://czmmiao.iteye.com/blog/1474678昨天客户反映说在下午某时间段有几个事务失败了,让我查下当时数据库系统的负载是否正常,看了下CPU的历史负载,很正常,于是看了下 ...

  9. .NET实现爬虫

    前几天看到一个.NET Core写成的爬虫,有些莫名的小兴奋,之前一直用集搜客去爬拉勾网的招聘信息,这个傻瓜化工具相当于用HTML模板页去标记DOM节点,然后在浏览器窗口上模拟人的浏览行为同时跟踪节点 ...

  10. winform 下载文件显示进度和百分比

    /// <summary> /// 下载完成 /// </summary> private void DownloadFileCompleted() { IsComlate = ...