[CF623E]Transforming Sequence
$\newcommand{\align}[1]{\begin{align*}#1\end{align*}}$题意:对于一个序列$a_{1\cdots n}(a_i\in[1,2^k-1])$,定义序列$b_{1\cdots n}$满足$b_i=a_1|\cdots|a_i$,这里的“$|$”是按位或,问有多少种可能的$a_{1\cdots n}$使得$b_{1\cdots n}$严格单调递增
首先,$a$每增加一个数,这个数必须有一个二进制位是前面所有数都没有出现过的,所以当$n\gt k$时是没有解的,那个$n\leq10^{18}$是在吓人
然后考虑DP,设$f_{i,j}$为$a$有$i$个数且这些数的或占了$j$个二进制位(占位不考虑顺序),那么答案为$\align{\sum\limits_{i=n}^k\binom kif_{n,i}}$(统计答案的时候就要考虑顺序了)
考虑如何转移,我们有$\align{f_{x+y,i}=\sum\limits_{j=0}^i\binom ijf_{x,j}\left(2^j\right)^yf_{y,i-j}}$(前$x$个数占据哪$j$位,后$y$个数必须占$i-j$位,后$y$个数的其他$j$位可以随便取),整理一下得到$\align{\dfrac{f_{x+y,i}}{i!}=\sum\limits_{j=0}^i\dfrac{f_{x,j}2^{yj}}{j!}\dfrac{f_{y,i-j}}{(i-j)!}}$,这是卷积的形式,并且第一维下标也是相加的形式,所以可以直接快速幂+FFT求得答案
可是模数是$10^9+7$...毒瘤出题人
所以学习了一发拆系数FFT:在模$p$意义下,我们可以选取一个$M\geq\left\lceil\sqrt p\right\rceil$,并且把每个系数表达为$aM+b$的形式(这时$a,b\leq M$,因为数字变小了所以爆精度的风险低一些),把每个多项式拆成两个多项式,稍微推下式子就可以做到用$7$次FFT完成任意模数卷积,注意合并系数时适当模一下防止爆$\text{long long}$
然后就做完了,感觉此题略神==
#include<stdio.h> #include<math.h> #include<string.h> typedef long long ll; typedef double du; const int mod=1000000007; int mul(int a,int b){return a*(ll)b%mod;} int pow(int a,int b){ int s=1; while(b){ if(b&1)s=mul(s,a); a=mul(a,a); b>>=1; } return s; } struct complex{ du x,y; complex(du a=0,du b=0){x=a;y=b;} }; complex operator+(complex a,complex b){return complex(a.x+b.x,a.y+b.y);} complex operator-(complex a,complex b){return complex(a.x-b.x,a.y-b.y);} complex operator*(complex a,complex b){return complex(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);} void swap(complex&a,complex&b){ complex c=a; a=b; b=c; } int rev[65536],N; complex w[16][65536]; void pre(int n){ int i,j,k; for(N=1,k=0;N<n;N<<=1)k++; for(i=0;i<N;i++)rev[i]=(rev[i>>1]>>1)|((i&1)<<(k-1)); k=0; for(i=2;i<=N;i<<=1){ for(j=0;j<i;j++)w[k][j]=complex(cos(j*M_PI/(i/2)),sin(j*M_PI/(i/2))); k++; } } void fft(complex*a,int on){ int i,j,k,f; complex t,wi; for(i=0;i<N;i++){ if(i<rev[i])swap(a[i],a[rev[i]]); } f=0; for(i=2;i<=N;i<<=1){ for(j=0;j<N;j+=i){ for(k=0;k<i>>1;k++){ wi=w[f][k]; wi.y*=on; t=wi*a[i/2+j+k]; a[i/2+j+k]=a[j+k]-t; a[j+k]=a[j+k]+t; } } f++; } if(on==-1){ for(i=0;i<N;i++)a[i].x/=N; } } complex A[65536],B[65536],C[65536],D[65536]; void mul(int*a,int*b,int n){ int i; complex t; for(i=0;i<N;i++){ A[i]=a[i]>>15; B[i]=a[i]&32767; C[i]=b[i]>>15; D[i]=b[i]&32767; } fft(A,1); fft(B,1); fft(C,1); fft(D,1); for(i=0;i<N;i++){ t=A[i]*D[i]+B[i]*C[i]; A[i]=A[i]*C[i]; C[i]=B[i]*D[i]; B[i]=t; } fft(A,-1); fft(B,-1); fft(C,-1); memset(a,0,(n+1)<<2); for(i=0;i<=n;i++)a[i]=((llround(A[i].x)%mod<<30)+(llround(B[i].x)%mod<<15)+llround(C[i].x)%mod)%mod; } int ta[65536]; void trans(int*a,int*b,int n,int p){ int i,t; memset(ta,0,sizeof(ta)); t=1; for(i=0;i<=n;i++){ ta[i]=mul(a[i],t); t=mul(t,p); } mul(ta,b,n); memcpy(a,ta,sizeof(ta)); } int fac[30010],rfac[30010]; int binom(int n,int k){return mul(fac[n],mul(rfac[k],rfac[n-k]));} int f[65536],g[65536]; int main(){ ll n; int k,i,b,ans; scanf("%I64d%d",&n,&k); if(n>k){ putchar('0'); return 0; } fac[0]=1; for(i=1;i<=k;i++)fac[i]=mul(fac[i-1],i); rfac[k]=pow(fac[k],mod-2); for(i=k;i>0;i--)rfac[i-1]=mul(rfac[i],i); for(i=1;i<=k;i++)f[i]=rfac[i]; g[0]=1; pre(k<<1|1); b=2; while(n){ if(n&1)trans(g,f,k,b); trans(f,f,k,b); b=mul(b,b); n>>=1; } ans=0; for(i=n;i<=k;i++)ans=(ans+mul(mul(g[i],fac[i]),binom(k,i)))%mod; printf("%d",(ans+mod)%mod); }
[CF623E]Transforming Sequence的更多相关文章
- BZOJ 5381 or & Codeforces 623E Transforming Sequence DP+NTT
两道题题意都是一样的 不过$CF$的模数是$10^9+7$ 很简单的分析发现$A_i$项一定要有一个之前没有出现过的二进制位才能满足条件 考虑$DP$来做 设$f_{i,j}$表示$i$个数用了二进制 ...
- CodeForces 623E Transforming Sequence 动态规划 倍增 多项式 FFT 组合数学
原文链接http://www.cnblogs.com/zhouzhendong/p/8848990.html 题目传送门 - CodeForces 623E 题意 给定$n,k$. 让你构造序列$a( ...
- 【codeforces 623E】 Transforming Sequence
http://codeforces.com/problemset/problem/623/E (题目链接) 题意 长度为${n}$的满足前缀按位或为单调递增的${k}$位序列.要求每个位置为${[1, ...
- Solution -「CF 623E」Transforming Sequence
题目 题意简述 link. 有一个 \(n\) 个元素的集合,你需要进行 \(m\) 次操作.每次操作选择集合的一个非空子集,要求该集合不是已选集合的并的子集.求操作的方案数,对 \(10^9 ...
- FFT/NTT复习笔记&多项式&生成函数学习笔记Ⅱ
因为垃圾电脑太卡了就重开了一个... 前传:多项式Ⅰ u1s1 我预感还会有Ⅲ 多项式基础操作: 例题: 26. CF438E The Child and Binary Tree 感觉这题作为第一题还 ...
- 多项式 之 快速傅里叶变换(FFT)/数论变换(NTT)/常用套路【入门】
原文链接https://www.cnblogs.com/zhouzhendong/p/Fast-Fourier-Transform.html 多项式 之 快速傅里叶变换(FFT)/数论变换(NTT)/ ...
- CF623
AIM Tech Round (Div. 1) <br > 这真是一套极好的题目啊.....虽然我不会做 <br > 代码戳这里 <br > A.Graph and ...
- FFT/FWT
最近舟游疯狂出货,心情很好~ FFT FWT 快速傅里叶变换(FFT) 具体的推导见这篇:胡小兔 - 小学生都能看懂的FFT!!! (写的很好,不过本小学生第一次没看懂0.0) 总结下关键内容 ~ P ...
- Note -「多项式」基础模板(FFT/NTT/多模 NTT)光速入门
进阶篇戳这里. 目录 何为「多项式」 基本概念 系数表示法 & 点值表示法 傅里叶(Fourier)变换 概述 前置知识 - 复数 单位根 快速傅里叶正变换(FFT) 快速傅里叶逆变换(I ...
随机推荐
- HTML5标签学习笔记
<!DOCTYPE html> <html lang="zh-cn"> <head> <meta http-equiv="con ...
- Springboot 启动问题
每次以debug方式启动springboot之后都会在SilentExitExceptionHandler类中的throw new SilentExitException() 解决办法 :window ...
- CodeForces-999D Equalize the Remainders
题目链接 https://vjudge.net/problem/CodeForces-999D 题面 Description You are given an array consisting of ...
- HDU 3111 Sudoku ( Dancing Links 精确覆盖模型 )
推荐两篇学DLX的博文: http://bbs.9ria.com/thread-130295-1-1.html(这篇对DLX的工作过程演示的很详细) http://yzmduncan.iteye.co ...
- JSP/Servlet Web 学习笔记 DayFive
ServletConfig <只对当前Servlet有效> (1)在Web容器初始化Servlet实例时,都会为这个Servlet准备一个唯一的ServletConfig实例(俗称Serv ...
- 【BestCoder #44】
因为这场比赛,我愉快地逃掉了晚自修. T1一开始各种SillyB,忘了40%的最低限制... T2各种想吐槽... 明明OJ警告说%lld是不行的我就换成%I64D(上面写这样的)... 结果各种WA ...
- 洛谷 P1503 鬼子进村 解题报告
P1503 鬼子进村 题目背景 小卡正在新家的客厅中看电视.电视里正在播放放了千八百次依旧重播的<亮剑>,剧中李云龙带领的独立团在一个县城遇到了一个鬼子小队,于是独立团与鬼子展开游击战. ...
- 设置(settings)
设置(settings) 题目描述 如题所示,这将是一个关于设置的问题. 你需要通过对一个控制台进行设置,来得到不同的效果. 这个控制台由n个控制元件组成,每个元件有m种设置,其中i号元件的第j种设置 ...
- HDU 5690 矩阵快速幂
All X Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submi ...
- java 复习整理(二 数据类型和几种变量)
源文件声明规则 当在一个源文件中定义多个类,并且还有import语句和package语句时,要特别注意这些规则. 一个源文件中只能有一个public类 一个源文件可以有多个非public类 源文件的名 ...