博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
bzoj 2962 序列操作——线段树(卷积?)
阅读量:5771 次
发布时间:2019-06-18

本文共 3558 字,大约阅读时间需要 11 分钟。

题目:

如果 _,_,_,…… 变成了 (_+k),(_+k),(_+k),…… ,计算就是在每个括号里选 _ 或 k ,乘起来求和。

为了算那个,枚举选了 j 个 k ;剩下那部分的乘积就是sm[cr][ i-j ]!j 和 k 可以在 len 里除了那 i-j 个位置里选,所以乘上 k^j 再乘上 C( len-(i-j) , j ) 。

调了2h+竟然只因组合数推导公式写错……

#include
#include
#include
#include
#define ll long longusing namespace std;const int N=5e4+5,Lm=20,mod=19940417;int n,q,t[N],tot,c[N][Lm+5],ans[Lm+5],tmp[Lm+5];int ls[N<<1],rs[N<<1],add[N<<1],sm[N<<1][Lm+5];bool rev[N<<1];char ch;int rdn(){ int ret=0;bool fx=1;char ch=getchar(); while(ch>'9'||ch<'0'){
if(ch=='-')fx=0;ch=getchar();} while(ch>='0'&&ch<='9') ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar(); return fx?ret:-ret;}void upd(int &x){x-=(x>=mod?mod:0);}void init(){ c[0][0]=1; for(int i=1;i<=n;i++)//n! for(int j=0;j<=i&&j<=Lm;j++) { c[i][j]=c[i-1][j]; if(j)c[i][j]+=c[i-1][j-1],upd(c[i][j]);//i-1 }}void pshp(int cr,int l,int mid,int r){ int lm=min(r-l+1,Lm),Ls=ls[cr],Rs=rs[cr]; for(int i=0;i<=lm;i++) { sm[cr][i]=0; for(int j=0;j<=i;j++) sm[cr][i]=(sm[cr][i]+(ll)sm[Ls][j]*sm[Rs][i-j])%mod; }// printf("pshp l=%d r=%d\n",l,r);// for(int i=0;i<=lm;i++)// printf(" sm[%d][%d]=%d\n",cr,i,sm[cr][i]);}void updt(int cr,int k,int len){ add[cr]+=k; upd(add[cr]); int lm=min(Lm,len); for(int i=lm;i>=0;i--) for(int j=1,ml=k;j<=i;j++,ml=(ll)ml*k%mod)//j=1 //j<=i not j<=lm { sm[cr][i]=(sm[cr][i]+(ll)sm[cr][i-j]*ml%mod*c[len-i+j][j])%mod;// if(cr==3&&i==2)// printf("smi=%d j=%d sm[i-j]=%d ml=%d c=[%d][%d]=%d\n",sm[cr][i],j,sm[cr][i-j],ml,len-i+j,j,c[len-i+j][j]); }// printf("updt\n");// for(int i=0;i<=lm;i++)// printf(" sm[%d][%d]=%d\n",cr,i,sm[cr][i]);}void updr(int cr,int lm){ if(add[cr])add[cr]=mod-add[cr]; rev[cr]^=1;//add for(int i=1;i<=lm;i+=2) if(sm[cr][i]) sm[cr][i]=mod-sm[cr][i];// printf("updr\n");// for(int i=0;i<=lm;i++)// printf(" sm[%d][%d]=%d\n",cr,i,sm[cr][i]);}void pshd(int cr,int l,int mid,int r){ int Ls=ls[cr],Rs=rs[cr]; if(rev[cr]) { rev[cr]=0; updr(Ls,min(mid-l+1,Lm)); updr(Rs,min(r-mid,Lm)); } if(add[cr]) { int k=add[cr]; add[cr]=0; updt(Ls,k,mid-l+1); updt(Rs,k,r-mid); }}void build(int l,int r,int cr){ if(l==r){sm[cr][1]=t[l];sm[cr][0]=1;return;} int mid=l+r>>1; ls[cr]=++tot; build(l,mid,ls[cr]); rs[cr]=++tot; build(mid+1,r,rs[cr]); pshp(cr,l,mid,r);}void mdfy(int l,int r,int cr,int L,int R,int v){ if(l>=L&&r<=R) {// printf("mdf: cr=%d l=%d r=%d\n",cr,l,r); updt(cr,v,r-l+1); return; } int mid=l+r>>1; pshd(cr,l,mid,r); if(L<=mid) mdfy(l,mid,ls[cr],L,R,v); if(mid
=L&&r<=R) {// printf("rev: cr=%d l=%d r=%d\n",cr,l,r); updr(cr,min(r-l+1,Lm)); return; } int mid=l+r>>1; pshd(cr,l,mid,r); if(L<=mid) revs(l,mid,ls[cr],L,R); if(mid
=L&&r<=R) { int lm=min(k,r-l+1); for(int i=k;i>=0;i--) for(int j=1;j<=lm&&j<=i;j++)//j<=i ans[i]=(ans[i]+(ll)sm[cr][j]*ans[i-j])%mod; return; } int mid=l+r>>1; pshd(cr,l,mid,r); if(L<=mid) query(l,mid,ls[cr],L,R,k); if(mid
>ch;scanf("%d%d",&a,&b); if(ch!='R')scanf("%d",&c); if(ch=='I') { c=c%mod+mod; upd(c); mdfy(1,n,1,a,b,c); } if(ch=='R') revs(1,n,1,a,b); if(ch=='Q') { for(int i=1;i<=c;i++)ans[i]=0; query(1,n,1,a,b,c); printf("%d\n",ans[c]); } } return 0;}

 

转载于:https://www.cnblogs.com/Narh/p/9722187.html

你可能感兴趣的文章
2016/08/25 The Secret Assumption of Agile
查看>>
(Portal 开发读书笔记)Portlet间交互-PortletSession
查看>>
搭建vsftpd服务器,使用匿名账户登入
查看>>
AMD改善Linux驱动,支持动态电源管理
查看>>
JAVA中循环删除list中元素的方法总结
查看>>
Java虚拟机管理的内存运行时数据区域解释
查看>>
人人都会深度学习之Tensorflow基础快速入门
查看>>
ChPlayer播放器的使用
查看>>
js 经过修改改良的全浏览器支持的软键盘,随机排列
查看>>
Mysql读写分离
查看>>
Oracle 备份与恢复学习笔记(5_1)
查看>>
Oracle 备份与恢复学习笔记(14)
查看>>
分布式配置中心disconf第一部(基本介绍)
查看>>
Scenario 9-Shared Uplink Set with Active/Active uplink,802.3ad(LACP)-Flex-10
查看>>
UML类图中的六种关系
查看>>
探寻Interpolator源码,自定义插值器
查看>>
一致性哈希
查看>>
mysql(待整理)
查看>>
使用PullToRefresh实现下拉刷新和上拉加载
查看>>
mysql
查看>>