【题解】数字组合(NTT+组合 滑稽)
【题解】数字组合(NTT+组合 滑稽)
今天实践一下谢总讲的宰牛刀233,滑稽。


\((1+x)(1+x)(1+x)\)的\(x^2\)系数就代表了有三个一快钱硬币构成的两块钱的方案数量。
很好理解,毕竟拆括号这种东西本身就有组合意义。
那么假设面值\(i\)有\(a_i\)个,那么最终的答案是
\]
的\(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+组合 滑稽)的更多相关文章
- 【AtCoder】AGC005 F - Many Easy Problems 排列组合+NTT
		
[题目]F - Many Easy Problems [题意]给定n个点的树,定义S为大小为k的点集,则f(S)为最小的包含点集S的连通块大小,求k=1~n时的所有点集f(S)的和取模92484403 ...
 - 【题解】【排列组合】【回溯】【Leetcode】Gray Code
		
The gray code is a binary numeral system where two successive values differ in only one bit. Given a ...
 - Scheme实现数字电路仿真(1)——组合电路
		
EDA是个很大的话题,本系列只针对其中一小部分,数字电路的仿真,叙述一点概念性的东西,并不会过于深入,这方面的内容实则是无底洞.本系列并不是真的要做EDA,按照SICP里的相关内容,采用Lisp的方言 ...
 - 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 ...
 - 【题解】【排列组合】【回溯】【Leetcode】Generate Parentheses
		
Given n pairs of parentheses, write a function to generate all combinations of well-formed parenthes ...
 - 【题解】【排列组合】【素数】【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 ...
 - 获得N位数字字母随机组合
		
import string import random def get_rand(n): allw = string.letters+string.digits r = [] for i in ran ...
 - JVM垃圾收集器组合--各种组合对应的虚拟机参数实践
		
前言 相信很多人都看过下面这张图,(来自<深入理解Java虚拟机:JVM高级特性与最佳实践>) 在学完几种垃圾收集器类型及组合后,打算看看实际中程序用到的垃圾收集器. 但是在jconsol ...
 - 剑指offer-拓展训练-字符的所有组合-全组合
		
/* 题目: 给定不含重复字符字符串的全组合. */ /* 思路: 递归法. 例给定abc,输出的组合长度为1,2,3. 对于长度为2的组合,分选择a(ab,ac)和不选择a的情况(bc). 选择a, ...
 
随机推荐
- JDK1.5新特性:
			
1.自动装箱与拆箱: 自动装箱的过程:每当需要一种类型的对象时,这种基本类型就自动地封装到与它相同类型的包装中. 自动拆箱的过程:每当需要一个值时,被装箱对象中的值就被自动地提取出来,没必要再去调用i ...
 - Jenkins集成java非maven/ant项目的打包思路
			
打包的思路如下: 1.使用javac命令对代码进行编译,比如递归编译整个项目的java代码.(注意:需要一一对应引用的jar包) 2.输出并整理war包的文件夹结构目录,参考:http://www.c ...
 - 【Objective-C Runtime动态加载】---动态创建类Class
			
a.使用objc_allocateClassPair创建一个类Class const char * className = "Calculator"; Class kc ...
 - weblogic的集群与配置图文
			
一.Weblogic的集群 还记得我们在第五天教程中讲到的关于Tomcat的集群吗? 两个tomcat做node即tomcat1, tomcat2,使用Apache HttpServer做请求派发 ...
 - MQ学习-RabbitMQ, ActiveMQ, Kafka等
			
之前学习过RabbitMQ,并且还安装过.安装记录的文章如下: Erlang:http://www.cnblogs.com/charlesblc/p/5512380.html RabbitMQ:htt ...
 - Scala 中Array,List,Tuple的差别
			
尽管学了一段时间的Scala了,可是总认为基础不是太扎实,还有非常多的基础知识比較模糊.于是近期又打算又一次学习基础. Scala中的三种集合类型包含:Array,List,Tuple.那么究竟这三种 ...
 - m3u8文件信息总结
			
近期在做视频下载.本地播放功能的时候.发现的问题,先笔记记录一下 开发思路 (1) 在线解析m3u8文件内容,把里面的ts相应连接的资源下载本地的Document文件下. (2) 把下载下来的资源使 ...
 - 【SharePoint】SharePoint2013中使用客户端对象模型给用户控件赋初值
			
本文要实现的功能:新建一条列表记录,打开新建记录画面时,自动给[申请人]赋值为当前登录用户. 在SharePoint2010中,可以使用SPServices的SPFindPeoplePicker方法来 ...
 - Python & Django & Pycharm 安装
			
一.下载安装Python 从https://www.python.org/上下载 Python 2.7.6,双击安装包开始安装: 单击“Next”按钮,进入Python安装组件选择界面.这里我们安装全 ...
 - 阿里云 RDS实例间的数据迁移
			
使用数据传输DTS可以实现两个RDS实例间的数据迁移.对于支持增量迁移的存储引擎,还可以使用DTS在源RDS实例不停服的情况下,将数据迁移到目标RDS实例.目前对于RDS不同存储引擎,只支持同构迁移( ...