5.20 省选模拟赛 求和 组合数的性质 EGF CRT
LINK:求和
绝妙的一道题目。没做绝对亏了.



对于第一个subtask 考虑直接递推出组合数.
对于第二个subtask 考虑EGF 设两个EGF 都只含偶数项指标且系数为1的那种 一个到n一个到m 容易发现要求的东西为 两个EGF的卷积.
code score: 30
const int MAXN=50010,maxn=600010,G=3;
int n,m,mod,lim;
int c[2][MAXN];
int fac[maxn],A[maxn],B[maxn],inv[maxn],rev[maxn];
inline int mul(int a,int b){return (ll)a*b%mod;}
inline int add(int a,int b){return a+b>=mod?a+b-mod:a+b;}
inline int mus(int a,int b){return a-b<0?a-b+mod:a-b;}
inline int ksm(int b,int p)
{
int cnt=1;
while(p)
{
if(p&1)cnt=mul(cnt,b);
b=mul(b,b);p=p>>1;
}
return cnt;
}
inline void NTT(int *a,int op)
{
rep(0,lim-1,i)if(i<rev[i])swap(a[i],a[rev[i]]);
for(int len=2;len<=lim;len=len<<1)
{
int mid=len>>1;
int wn=ksm(G,op==1?(mod-1)/len:mod-1-(mod-1)/len);
for(int j=0;j<lim;j+=len)
{
int d=1;
for(int i=0;i<mid;++i)
{
int x=a[i+j],y=mul(a[i+j+mid],d);
a[i+j]=add(x,y);a[i+j+mid]=mus(x,y);
d=mul(d,wn);
}
}
}
if(op==-1)
{
int INV=ksm(lim,mod-2);
rep(0,lim-1,i)a[i]=mul(a[i],INV);
}
}
int main()
{
freopen("c.in","r",stdin);
freopen("c.out","w",stdout);
get(n);get(m);get(mod);
if(n&1)--n;if(m&1)--m;
m=min(n,m);
if(n<=5000&&m<=5000)
{
int ans=1;
c[0][0]=1;
rep(1,n,i)
{
rep(0,min(i,m),j)
{
if(!j)c[i&1][j]=1;
else c[i&1][j]=add(c[(i-1)&1][j-1],c[(i-1)&1][j]);
if(!(i&1)&&!(j&1))ans=add(ans,c[i&1][j]);
}
}
put(ans);return 0;
}
if(n<=200000&&m<=200000&&mod==998244353)
{
fac[0]=1;
rep(1,n,i)fac[i]=mul(fac[i-1],i);
inv[n]=ksm(fac[n],mod-2);
fep(n-1,0,i)inv[i]=mul(inv[i+1],i+1);
for(int i=0;i<=n;i+=2)A[i]=inv[i];
for(int i=0;i<=m;i+=2)B[i]=inv[i];
lim=1;while(lim<=n+m)lim=lim<<1;
rep(0,lim-1,i)rev[i]=rev[i>>1]>>1|((i&1)?lim>>1:0);
NTT(A,1);NTT(B,1);
rep(0,lim-1,i)A[i]=mul(A[i],B[i]);
NTT(A,-1);int ans=0;
rep(0,n,i)
{
if(i&1)continue;
A[i]=mul(A[i],fac[i]);
ans=add(ans,A[i]);
}
put(ans);
return 0;
}
}
我只能做这么多了。
剩下的考虑先推一些关于组合数的式子.
先考虑题解的绝妙式子吧:
将C(i,j)变成二项式定理展开后的式子 那么原式=
\(\sum_{j=0}^m\sum_{i=0}^n [x^j](x+1)^i,i\mod 2==0,j\mod 2==0\)
容易发现第二项是一个等比数列 可以先求一下和. 将n变成偶数。
设\(F(x)=\frac{(x+1)^{n+2}-1}{(x+1)^2-1}\)
所求就变成了\(\sum_{j=0}^m[j\mod 2==0][x^j]F(x)\)
(剩下需要 高深的东西了 二阶线性递推
源神给我讲了他的做法:
设\(g_j=\sum_{i=0}^nC(i,j)[i\mod 2==0],l_j=\sum_{i=0}^nC(i,j)[i\mod 2==1]\)


所以就可以递推出g了。
subtask3 很容易就解决了。(注意 组合数中有和mod相等的数的出现.
subtask4 可能不存在逆元了 通常都是 质因数分解然后CRT合并.
2的逆元还存在 所以还是可以递推的 复杂度 mlog^2 log很小 所以可以过。
subtask5 2的逆元可能不存在了 单独考虑模数2^b.
把递推式倒着写发现就没有除以2的问题了 考虑如何先求出gm.
做法如下:

code:
const int MAXN=1000050,maxn=50;
int n,m,B,ww,xx,yy,cnt,mod;
int w[maxn],p[maxn],f[maxn],v[maxn],phi[maxn],IN[maxn];
int C[MAXN],g[MAXN],G[MAXN];
inline void exgcd(int a,int b)
{
if(!b){xx=1;yy=0;return;}
exgcd(b,a%b);
int zz=xx;xx=yy;yy=zz-a/b*yy;
}
inline int inv(int a,int b)
{
exgcd(a,b);
return (xx%b+b)%b;
}
inline int ksm(int b,int p,int mod)
{
int cnt=1;
while(p)
{
if(p&1)cnt=(ll)cnt*b%mod;
b=(ll)b*b%mod;p=p>>1;
}
return cnt;
}
int main()
{
freopen("c.in","r",stdin);
freopen("c.out","w",stdout);
get(n);get(m);get(mod);ww=mod;
if(n&1)--n;if(m&1)--m;
if(mod==1){puts("0");return 0;}
m=min(n,m);
for(int i=2;i*i<=ww;++i)
if(ww%i==0)
{
p[++cnt]=i;
w[cnt]=f[cnt]=1;v[cnt]=0;
while(ww%i==0)
{
w[cnt]*=i;
ww/=i;
}
phi[cnt]=w[cnt]/i*(i-1);
IN[cnt]=inv(mod/w[cnt],w[cnt]);
}
if(ww>1)
{
p[++cnt]=ww;w[cnt]=ww;
f[cnt]=1;v[cnt]=0;
phi[cnt]=ww-1;
IN[cnt]=inv(mod/w[cnt],w[cnt]);
}
C[0]=1;
rep(1,min(n+2,m+32),i)
{
int ans=0;
rep(1,cnt,j)
{
int w1=n+2-i+1;
int w2=i;
while(w1%p[j]==0)
{
++v[j];
w1/=p[j];
}
while(w2%p[j]==0)
{
--v[j];
w2/=p[j];
}
f[j]=(ll)f[j]*w1%w[j]*ksm(w2,phi[j]-1,w[j])%w[j];
int v1=(ll)ksm(p[j],v[j],w[j])*f[j]%w[j];
ans=(ans+(ll)IN[j]*v1%mod*(mod/w[j]))%mod;
}
C[i]=ans;
}
int w1=p[1]==2?mod/w[1]:mod;
int ans=0;
g[0]=n/2+1;ans=g[0]%=w1;
int INV=inv(2,w1);
rep(1,m,i)
{
g[i]=((ll)(C[i+1]-g[i-1])%w1*INV%w1+w1)%w1;
if(!(i&1))ans=(ans+g[i])%w1;
}
if(p[1]==2)
{
int cc=w[1];
while(cc!=1)
{
++B;
cc=cc>>1;
}
cc=1;int ans1=0;
rep(0,B-1,i)G[m]=(G[m]+(ll)cc*C[i+m+2])%w[1],cc=cc*(-2)%w[1];
ans1=G[m];
fep(m-1,0,i)
{
G[i]=(C[i+2]-(ll)2*G[i+1])%w[1];
if(!(i&1))ans1=(ans1+G[i])%w[1];
}
//合并 ans1 ans
int c1=inv(mod/w[1],w[1]);
int c2=inv(mod/w1,w1);
ans=((ll)ans*c2%mod*(mod/w1)%mod+(ll)ans1*c1%mod*(mod/w[1])%mod)%mod;
}
ans+=mod;ans%=mod;put(ans);
return 0;
}
5.20 省选模拟赛 求和 组合数的性质 EGF CRT的更多相关文章
- 5.20 省选模拟赛 T1 图 启发式合并 线段树合并 染色计数问题
LINK:图 在说这道题之前吐槽一下今天的日子 520 = 1+1+4+514. /cy 这道题今天做的非常失败 一点分都没拿到手 关键是今天的T3 把我整个人给搞崩了. 先考虑 如果得到了这么一张图 ...
- 【洛谷比赛】[LnOI2019]长脖子鹿省选模拟赛 T1 题解
今天是[LnOI2019]长脖子鹿省选模拟赛的时间,小编表示考的不怎么样,改了半天也只会改第一题,那也先呈上题解吧. T1:P5248 [LnOI2019SP]快速多项式变换(FPT) 一看这题就很手 ...
- @省选模拟赛03/16 - T3@ 超级树
目录 @description@ @solution@ @accepted code@ @details@ @description@ 一棵 k-超级树(k-SuperTree) 可按如下方法得到:取 ...
- 3.28 省选模拟赛 染色 LCT+线段树
发现和SDOI2017树点涂色差不多 但是当时这道题模拟赛的时候不会写 赛后也没及时订正 所以这场模拟赛的这道题虽然秒想到了LCT和线段树但是最终还是只是打了暴力. 痛定思痛 还是要把这道题给补了. ...
- 【2018.10.20】noip模拟赛Day3 飞行时间
今天模拟赛题目 纯考输入的傻逼题,用$scanf$用到思想僵化的我最终成功被$if$大法爆$0$了(这题只有一组$100$分数据). 输入后面那个$(+1/2)$很难$if$判断,所以我们要判两个字符 ...
- 4.9 省选模拟赛 生成树求和 变元矩阵树定理 生成函数 iDFT 插值法
有同学在loj上找到了加强版 所以这道题是可以交的.LINK:生成树求和 加强版 对于30分 爆搜 可实际上我爆搜只过了25分 有同学使用按秩合并并茶几的及时剪枝通过了30分. const int M ...
- NOI2019省选模拟赛 第五场
爆炸了QAQ 传送门 \(A\) \(Mas\)的童年 这题我怎么感觉好像做过--我记得那个时候还因为没有取\(min\)结果\(100\to 0\)-- 因为是个异或我们肯定得按位考虑贡献了 把\( ...
- NOI2019省选模拟赛 第六场
传送门 又炸了-- \(A\) 唐时月夜 不知道改了什么东西之后就\(A\)掉了\(.jpg\) 首先,题目保证"如果一片子水域曾经被操作过,那么在之后的施法中,这片子水域也一定会被操作&q ...
- FCS省选模拟赛 Day5
传送门 Solution Code #include<bits/stdc++.h> #define ll long long #define max(a,b) ((a)>(b)?( ...
随机推荐
- html中doctype有几种类型 以及doctype的作用
htm中doctype标签是一种标准通用标记语言的文档类型声明,它的目的是要告诉标准通用标记语言解析器,它应该使用什么样的文档类型定义(DTD)来解析文档. dotype 的特点: <!doct ...
- SQL基础随记1 SQL分类 常用函数 ALL ANY EXISTS IN 约束
SQL基础随记1 SQL分类 常用函数 ALL ANY EXISTS IN 约束 其实这里知识不难,只是好久不接触突然被问的话有时还真的一时答不上,自己写一遍胜过盲扫.当然,也有些常读常新的地方会 ...
- JSR 303 进行后台数据校验
一.JSR 303 1.什么是 JSR 303? JSR 是 Java Specification Requests 的缩写,即 Java 规范提案. 存在各种各样的 JSR,简单的理解为 JSR 是 ...
- day33 网络编程(下)
目录 上节课回顾: 一.传输层 二.应用层 三.socket 四.如何获取目标ip地址 五.网络通信的流程 上节课回顾: 通过ip地址如何找到另外一台设备 ip地址分为子网部分和主机部分 我们要和其他 ...
- Alink漫谈(十) :线性回归实现 之 数据预处理
Alink漫谈(十) :线性回归实现 之 数据预处理 目录 Alink漫谈(十) :线性回归实现 之 数据预处理 0x00 摘要 0x01 概念 1.1 线性回归 1.2 优化模型 1.3 损失函数& ...
- Django之重写用户模型
django——重写用户模型 Django内建的User模型可能不适合某些类型的项目.例如,在某些网站上使用邮件地址而不是用户名作为身份的标识可能更合理. 1.修改配置文件,覆盖默认的User模型 D ...
- 什么是控制反转(IoC)?什么是依赖注入(DI)?以及实现原理
IoC不是一种技术,只是一种思想,一个重要的面向对象编程的法则,它能指导我们如何设计出松耦合.更优良的程序.传统应用程序都是由我们在类内部主动创建依赖对象,从而导致类与类之间高耦合,难于测试:有了 ...
- 性能测试必备知识(2)- 查看 Linux 的 CPU 相关信息
做性能测试的必备知识系列,可以看下面链接的文章哦 https://www.cnblogs.com/poloyy/category/1806772.html 查看系统 CPU 信息 cat /proc/ ...
- Jmeter操作MySQL数据库详解
一.jmeter操作数据库的原理 jmeter不可直接操作数据库,必须通过驱动程序来间接操作,但如果数据库不是在本地而是云服务器上的话就需要通过网络来操作. jmeter通过驱动程序来完成对MySQL ...
- Shell基本语法---case语句
case语句 格式 case 变量 in 值1 ) 执行动作1 ;; 值2 ) 执行动作2 ;; 值3 ) 执行动作3 ;; .... * ) 如果变量的值都不是以上的值,则执行此程序 ;; esac ...