uoj#420. 【集训队作业2018】矩形(组合数学)
题面
题解
这辣鸡题目做了咱整整三天……咱果然还是太菜了……好珂怕的推倒啊……
首先把它变成
\sum_{i = 1}^{n} \sum_{j = 1}^{m} F(i, j) \, h^{im + j}
\right) \bmod p\]
那么最后求答案的时候乘上的\({1\over h^{m+1}}\)就行了
我们考虑对\(v\)(即题目中的\(f_i\))和\(c\)分别计算贡献
\(sub_1\)
对于\(v_x\),打个表可以发现,第\(x\)行第\(1\)列它的系数为\(b\),第\(2\)列系数为\(b^2\),以及第\(x+i\)行第\(j\)列的系数为\({i+j-1\choose j-1}a^ib^jh^{(i+x)m}h^j\)
我们对它的系数求和,就是
cnt
&=\sum_{i=0}^{n-x}a^ih^{(i+x)m}\sum_{j=1}^{m}{i+j-1\choose j-1}b^{j}h^{j}\\
&=bh^{xm+1}\sum_{i=0}^{n-x}a^ih^{im}\sum_{j=0}^{m-1}{i+j\choose j}b^{j}h^{j}\\
\end{aligned}
\]
记
f_n=\sum_{i=0}^na^ih^{im}\sum_{j=0}^{m-1}{i+j\choose j}b^{j}h^{j}\\
g_n=\sum_{j=0}^{m-1}{n+j\choose j}b^{j}h^{j}\\
\end{aligned}
\]
于是我们显然可以写出\(f_n\)的递推式\(f_n=f_{n-1}+a^nh^{nm}g_n\)
那么我们只要能搞出\(g\)就可以求出\(f\),进而求出每个\(v_x\)的系数了
那么继续推倒
g_n
&=\sum_{j=0}^{m-1}{n+j\choose j}b^{j}h^{j}\\
&=\sum_{j=0}^{m-1}\left({n+j-1\choose j-1}+{n-1+j\choose j}\right)b^{j}h^{j}\\
&=bh\sum_{j=0}^{m-2}{n+j\choose j}b^{j}h^{j}+\sum_{j=0}^{m-1}{n-1+j\choose j}b^{j}h^{j}\\
&=bh\left(g_n-{n+m-1\choose m-1}b^{m-1}h^{m-1}\right)+g_{n-1}
\end{aligned}
\]
然后就分类讨论啊,如果\(bh\)等于\(1\),就消掉\(g_n\),可以直接得出\(g_{n-1}\)的式子。如果\(bh\)不等于\(1\),就移项解方程。于是
{n+m\choose m-1}&bh=1\\
{g_{n-1}+{n+m-1\choose m-1}b^mh^m\over 1-bh}&bh\neq 1
\end{cases}
\]
初值分别为\(m(bh=1)\)和\({1-b^mh^m\over 1-bh}(bh\neq 1)\)
然后递推出\(g\),进而求出\(f\),对于每个\(v_x\)乘上\(bh^{xm+1}\)和\(f_{n-x}\)就行了
\(sub_2\)
然后我们考虑\(c\)的贡献
对于位置\((x,y)\),\((i,j)(i\leq x,j\leq y)\)上的每一个\(c\)都会对这一个位置有贡献,我们可以看做向下走一步乘\(a\),向右走一步乘\(b\),\((x,y)\)上\(c\)的系数就是从所有\((i,j)\)走到它的所有路径的权值之和。那么这个位置上\(c\)的系数就是就是
\]
总的系数就是
\]
我们记\(G(x,y)=h^y\sum_{i=0}^{x-1}\sum_{j=0}^{y-1}a^ib^j{i+j\choose j}\)
和上面一样化简。
G(x,y)
&=h^y\sum_{i=0}^{x-1}\sum_{j=0}^{y-1}a^ib^j\left({i+j-1\choose j-1}+{i-1+j\choose j}\right)\\
&=h^ya\sum_{i=0}^{x-2}\sum_{j=0}^{y-1}a^ib^j{i+j\choose j}+h^yb\sum_{i=0}^{x-1}\sum_{j=0}^{y-2}a^ib^j{i+j\choose j}+h^y
\end{aligned}
\]
注意,中间把组合数拆开来的时候,这个式子对\({0\choose 0}\)实际上是不适用的,所以我们少算了\({0\choose 0}\)的贡献,所以最后要加上\(h^y\)(咱因为没发现这个细节卡了好久)
继续推倒
\]
我们对这个东西求一个和,也就是记\(T(x)=\sum_{y=1}^m G(x,y)\),有
\]
虽然最后的\(h^y\)的求和还要特判一下\(h=1\)的情况不过想必大家都是明白的我就不写了
中间那一大坨是什么东西啊……回过头去看看……
\(\sum_{j=0}^{m-1}b^jh^j{i+j\choose j}\)不等于\(g_i\)么……
\]
还是分类讨论,如果\(b=1\)我们可以直接求出\(T(x-1)\)的通项公式,否则就可以解出\(T(x)\)的递推公式
然后枚举\(x\),每一个\(x\)都要让系数加上\(h^{xm}T(x)\),最后系数乘上\(c\)就行了
搞清楚字母哪个是哪个,别跟咱一样连自己写的啥都不知道了……
//minamoto
#include<bits/stdc++.h>
#define R register
#define ll long long
#define fp(i,a,b) for(R int i=a,I=b+1;i<I;++i)
#define fd(i,a,b) for(R int i=a,I=b-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
using namespace std;
char buf[1<<21],*p1=buf,*p2=buf;
inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
int read(){
R int res,f=1;R char ch;
while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
return res*f;
}
const int N=1e6+15;
int v[N],f[N],g[N],d[N],inv[N],t[N];
int n,m,h,P,a,b,c,res,x,y;
inline int add(R int x,R int y){return x+y>=P?x+y-P:x+y;}
inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;}
inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;}
int ksm(R int x,R ll y){
R int res=1;
for(;y;y>>=1,x=mul(x,x))if(y&1)res=mul(res,x);
return res;
}
int calc1(){
int res=0,tmp;
if(mul(b,h)==1){
f[0]=g[0]=tmp=m;
fp(i,1,n){
tmp=1ll*(i+m)%P*tmp%P*inv[i+1]%P;
g[i]=tmp;
}
}else{
int p=mul(b,h),q=ksm(p,m);
p=ksm(dec(1,p),P-2);
tmp=1,f[0]=g[0]=mul(dec(1,q),p);
fp(i,1,n){
tmp=1ll*(i+m-1)%P*tmp%P*inv[i]%P;
g[i]=dec(g[i-1],mul(tmp,q)),g[i]=mul(g[i],p);
}
}
int p=1,k=mul(a,ksm(h,m));
fp(i,1,n)p=mul(p,k),f[i]=add(f[i-1],mul(p,g[i]));
int x=mul(b,h),y=ksm(h,m);
fp(i,1,n)x=mul(x,y),res=add(res,1ll*x*f[n-i]%P*v[i]%P);
return res;
}
int calc2(){
int res=0,qwq=(h==1)?m%P:1ll*h*dec(1,ksm(h,m))%P*ksm(dec(1,h),P-2)%P;
if(b==1){
int tmp=g[0],k=1,inva=ksm(a,P-2);
fp(i,1,n)k=mul(k,a),tmp=add(tmp,mul(k,g[i])),t[i]=mul(dec(1ll*tmp*h%P*b%P,qwq),inva);
}else{
int tmp=g[0],k=1,invb=ksm(dec(1,b),P-2);
fp(i,1,n){
t[i]=mul(a,t[i-1]);
t[i]=dec(t[i],1ll*b*h%P*tmp%P);
t[i]=add(t[i],qwq);
t[i]=mul(t[i],invb);
k=mul(k,a),tmp=add(tmp,mul(k,g[i]));
}
}
int g=1,k=ksm(h,m);
fp(i,1,n)g=mul(g,k),res=add(res,mul(g,t[i]));
return mul(res,c);
}
int main(){
// freopen("testdata.in","r",stdin);
read(),n=read(),m=read(),h=read(),P=read(),a=read(),b=read(),c=read();
if(!h)return printf("%d\n",add(c,mul(b,read()))),0;
inv[0]=inv[1]=1;fp(i,2,n+5)inv[i]=mul(P-P/i,inv[P%i]);
fp(i,1,n)v[i]=read();
x=calc1(),y=calc2();
res=ksm(h,m+1),res=ksm(res,P-2),res=mul(res,add(x,y));
printf("%d\n",res);
return 0;
}
uoj#420. 【集训队作业2018】矩形(组合数学)的更多相关文章
- uoj #450[集训队作业2018]复读机
传送门 \(d=1\),那么任何时刻都可以\(k\)个复读机的一种,答案为\(k^n\) \(d>1\),可以枚举某个复读机的复读次数(必须是\(d\)的倍数),然后第\(i\)个复读时间为\( ...
- UOJ 422 [集训队作业2018] 小Z的礼物 min-max容斥 期望 轮廓线dp
LINK:小Z的礼物 太精髓了 我重学了一遍min-max容斥 重写了一遍按位或才写这道题的. 还是期望多少时间可以全部集齐. 相当于求出 \(E(max(S))\)表示最后一个出现的期望时间. 根据 ...
- UOJ #449. 【集训队作业2018】喂鸽子
UOJ #449. [集训队作业2018]喂鸽子 小Z是养鸽子的人.一天,小Z给鸽子们喂玉米吃.一共有n只鸽子,小Z每秒会等概率选择一只鸽子并给他一粒玉米.一只鸽子饱了当且仅当它吃了的玉米粒数量\(≥ ...
- 【UOJ#450】【集训队作业2018】复读机(生成函数,单位根反演)
[UOJ#450][集训队作业2018]复读机(生成函数,单位根反演) 题面 UOJ 题解 似乎是\(\mbox{Anson}\)爷的题. \(d=1\)的时候,随便怎么都行,答案就是\(k^n\). ...
- 【UOJ#422】【集训队作业2018】小Z的礼物(min-max容斥,轮廓线dp)
[UOJ#422][集训队作业2018]小Z的礼物(min-max容斥,轮廓线dp) 题面 UOJ 题解 毒瘤xzy,怎么能搬这种题当做WC模拟题QwQ 一开始开错题了,根本就不会做. 后来发现是每次 ...
- UOJ#418. 【集训队作业2018】三角形
#418. [集训队作业2018]三角形 和三角形没有关系 只要知道儿子放置的顺序,就可以直接模拟了 记录历史最大值 用一个pair(a,b):之后加上a个,期间最大值为增加b个 合并? A1+A2= ...
- UOJ#422. 【集训队作业2018】小Z的礼物
#422. [集训队作业2018]小Z的礼物 min-max容斥 转化为每个集合最早被染色的期望时间 如果有x个选择可以染色,那么期望时间就是((n-1)*m+(m-1)*n))/x 但是x会变,中途 ...
- UOJ#428. 【集训队作业2018】普通的计数题
#428. [集训队作业2018]普通的计数题 模型转化好题 所以变成统计有标号合法的树的个数. 合法限制: 1.根标号比子树都大 2.如果儿子全是叶子,数量B中有 3.如果存在一个儿子不是叶子,数量 ...
- uoj450 【集训队作业2018】复读机(生成函数,单位根反演)
uoj450 [集训队作业2018]复读机(生成函数,单位根反演) uoj 题解时间 首先直接搞出单个复读机的生成函数 $ \sum\limits_{ i = 0 }^{ k } [ d | i ] ...
- [UOJ422][集训队作业2018]小Z的礼物——轮廓线DP+min-max容斥
题目链接: [集训队作业2018]小Z的礼物 题目要求的就是最后一个喜欢的物品的期望得到时间. 根据$min-max$容斥可以知道$E(max(S))=\sum\limits_{T\subseteq ...
随机推荐
- (转)c# Linq及Lamda表达式应用经验之 GroupBy 分组
本文转载自:http://www.cnblogs.com/han1982/p/4138163.html 示例1: GroupBy 分组在List<>泛型中的应用 原表: 按姓名Nam 分组 ...
- java流的操作步骤、、
在java中使用IO操作必须按照以下的步骤完成: 使用File找到一个文件 使用字节流或字符流的子类为OutputStream.InputStream.Writer.Reader进行实例化操 作 ...
- 深入理解Java虚拟机—JVM内存结构
1.概述 jvm内存分为线程共享区和线程独占区,线程独占区主要包括虚拟机栈.本地方法栈.程序计数器:线程共享区包括堆和方法区 2.线程独占区 虚拟机栈 虚拟机栈描述的是java方法执行的动态内存模型, ...
- sys模块 进度条百分比
用于提供对Python解释器相关的操作: sys.argv 命令行参数List,第一个元素是程序本身路径 sys.exit(n) 退出程序,正常退出时exit(0) ...
- python笔记--3--函数、生成器、装饰器、函数嵌套定义、函数柯里化
函数 函数定义语法: def 函数名([参数列表]): '''注释''' 函数体 函数形参不需要声明其类型,也不需要指定函数返回值类型 即使该函数不需要接收任何参数,也必须保留一对空的圆括号 括号后面 ...
- 用于.NET环境的时间测试(转)
用于.NET环境的时间测试 在.NET环境中,衡量运行完整算法所花费的时间长度,需要考虑很多 需要考虑很多种情况 ,如:程序运行所处的线程以及无用单位收集(GC垃圾回收). 在程序执行过程中无用单 ...
- nodejs读文件
1.异步读取文件:var fs= require('fs'); // 从文件系统中读取请求的文件内容 fs.readFile(pathname.substr(1), function (err, da ...
- 面试题:3年工作经验 已看1 有用 memcache和redis有什么区别
此内容偏中高级,适合有三年经验者. 1. java中wait和sleep有什么区别?多线程条件下如何保证数据安全? 答:最大区别是等待时wait会释放锁(乐观锁),而sleep会一直持有锁 ...
- 算法Sedgewick第四版-第1章基础-024-M/M/1 queue
/****************************************************************************** * Compilation: javac ...
- Android 中的菜单 OptionsMenu的简单应用
OptionsMenu就是安卓手机中的菜单选项 首先 要实现对菜单的操作就要先重写OnCreateOptionsMenu(Menu menu)方法 通常有两种方法来实现对菜单中选项的添加 第一种是动态 ...