HZOJ 20190722 visit (组合数学+数论)
考试T2,考试时打了个$O(n^3)$dp暴力,思路还是很好想的,但细节也不少,然后滚动数组没清空,而且题又看错了,只得了10pts,真是血的教训。
题解:
其实看数据范围,给出了模数是否为质数,其实应该能推测出这是道数学题(但是不会推式子啊)
我们仔细分析一下问题,我们设$ri,le,up ,down$分别为向右左上下走的步数,且总步数为T,然后我们只要知道,向一个方向走的步数就能得到其他的,但是我们发现光凭一个是求不出的,我们再转化一下思路,我们设在上下方向走的步数为$k$,则$up+down=k$,然后又因为他最后必须走到$(n,m)$,所以向上走的步数减去向下走的步数为$m$,即$up-down=m$,同理我们可以求出$ri$与$le$的关系,同样是两个方程,这样我们就可以通过枚举$k$,来得到向各个方向走的步数,这样就能列出组合数的式子了,即:
$\sum \limits_{k=m}^{t-n}C_t^k*C_k^{\frac{k-m}{2}}*C_{n-k}^{\frac{t-k-n}{2}}$
这题貌似到这里就结束了,但是我们注意到他的模数$p$并不一定是一个质数,所以我们用普通lucas是求不出来的,而ex_lucas又过于难写,且运行慢,其实是因为我不会哪又要怎么办呢,我们看他的数据范围中说模数p分解质因数后的每个质因子的次数都为1,那么我们就可以利用这个性质,先用普通lucas求出答案对每个质因子答案,然后用CRT合并即可。
要注意的几点:对于每个质因子求答案时都要处理一遍阶乘表,不然就会不对
一定要多取模,尤其是连乘的时候,不然很容易崩
枚举k时要$k+=2$因为他在上下方向或左右方向的变化量不可能为1
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<vector>
#include<queue>
#define int long long
using namespace std;
const int N=;
int flag=;int t,n,m;
int dp[N][N][N];
int prime[N],a[N],inv[],res[N];
int fac[];
int qpow(int a,int b,int p){
int ans=;
while(b){
if(b&) ans=ans*a%p;
b>>=;
a=a*a%p;
}
return ans%p;
}
int C(int n,int m,int p){
if(n<m) return ;
else return fac[n]%p*qpow(fac[n-m]*fac[m]%p,p-,p)%p;
}
int lucas(int a,int b,int p){
if(!b) return ;
else return lucas(a/p,b/p,p)%p*C(a%p,b%p,p)%p;
}
void divide(int p){
for(int i=;i<=sqrt(p);i++){
if(p%i==){
flag++;
prime[flag]=i;
p/=i;
}
}
if(p>) prime[++flag]=p;
}
int exgcd(int a,int b,int &x,int &y){
int t;
if(!b){
x=;y=;return a;
}
t=exgcd(b,a%b,x,y);
t=x;
x=y;
y=t-a/b*y;
}
int CRT(){
int ans=;
int M=;
for(int i=;i<=flag;i++) M*=prime[i];
for(int i=;i<=flag;i++){
ans=(ans+M/prime[i]*res[i]%M*qpow(M/prime[i],prime[i]-,prime[i])%M)%M;
}
return ans;
}
int init(int p){
int minn=min(p-,t);
fac[]=;
for(int i=;i<=minn;i++){
fac[i]=fac[i-]*i%p;
}
}
signed main(){
int p;
scanf("%lld%lld%lld%lld",&t,&p,&n,&m);
m=abs(m);n=abs(n);
divide(p);
if(t<=){
int dd=;
dp[][dd][dd]=;
for(int i=;i<=t;i++){
for(int j=-t;j<=t;j++){
for(int k=-t;k<=t;k++){
dp[i][j+dd][k+dd]=(dp[i][j+dd][k+dd]+dp[i-][j++dd][k+dd]+dp[i-][j+dd][k++dd]+dp[i-][j-+dd][k+dd]+dp[i-][j+dd][k-+dd])%p;
}
}
}
printf("%lld",dp[t][n+dd][m+dd]);
return ;
}
int ans=;
fac[]=;
//for(int i=1;i<=100005;i++) fac[i]=fac[i-1]*i%p;
for(int i=;i<=flag;i++){
init(prime[i]);
for(int k=n;k<=t-m;k+=){//i+=2
res[i]=(res[i]+lucas(t,k,prime[i])*lucas(k,(k-n)/,prime[i])%p*lucas(t-k,(t-m-k)/,prime[i]))%p;
}
}
printf("%lld",CRT()%p);
}
HZOJ 20190722 visit (组合数学+数论)的更多相关文章
- Bzoj 4403: 序列统计 Lucas定理,组合数学,数论
4403: 序列统计 Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 328 Solved: 162[Submit][Status][Discuss] ...
- hdu 6088 Rikka with Rock-paper-scissors (2017 多校第五场 1004) 【组合数学 + 数论 + 模意义下的FFT】
题目链接 首先利用组合数学知识,枚举两人的总胜场数容易得到 这还不是卷积的形式,直接搞的话复杂度大概是O(n^2)的,肯定会TLE.但似乎和卷积有点像?想半天没想出来..多谢Q巨提醒,才知道可以用下面 ...
- poj 2154 Color < 组合数学+数论>
链接:http://poj.org/problem?id=2154 题意:给出两个整数 N 和 P,表示 N 个珠子,N种颜色,要求不同的项链数, 结果 %p ~ 思路: 利用polya定理解~定理内 ...
- 退役之战- SDOI
嘻嘻, 从文化课中逃脱出来, 很痛苦啊, 英语已经近半年没学了,语文水平水的一批,在其他班里受虐待. 百废待兴. 因为曾经学了一段时间的省选,所以被老师拉回来送人头考试啦. 听说4.5 SDOI一轮哎 ...
- Codeforces Round #519
题目链接:传送门 A. Elections (思维+暴力) 思路: 从最小的k开始枚举就好了- -. #include <bits/stdc++.h> using namespace ...
- 模意义下的FFT算法
//写在前面 单就FFT算法来说的话,下面只给出个人认为比较重要的推导,详细的介绍可参考 FFT算法学习笔记 令v[n]是长度为2N的实序列,V[k]表示该实序列的2N点DFT.定义两个长度为N的实序 ...
- 模拟7题解 T2visit
T2 visit [组合数学][中国剩余定理] 一场考试难得见两个数学题 本来想矩阵快速幂,显然空间复杂度不行,主要是没时间,就没打 正解: 首先推波式子 1.$C_{t}^{k}$ 在t步中总 ...
- 【51Nod1769】Clarke and math2(数论,组合数学)
[51Nod1769]Clarke and math2(数论,组合数学) 题面 51Nod 题解 考虑枚举一个\(i_k\),枚举一个\(i\),怎么计算\(i_k\)对\(i\)的贡献. 把\(\f ...
- 数论 - 组合数学 + 素数分解 --- hdu 2284 : Solve the puzzle, Save the world!
Solve the puzzle, Save the world! Problem Description In the popular TV series Heroes, there is a ta ...
随机推荐
- 记录 OpenCV 错误
最近在做一个"人脸识别"的项目,我想用OpenCV来分析图片中的人脸. 但是在测试的时候,程序报出“检测到0张脸” 可能的错误原因: 1.教程中OpenCV的版本问题,教程中用的版 ...
- Java 日志系统
Java 日志系统 1. 创建日志记录器 private final Logger logger = LoggerFactory.getLogger(LoggerTest.class); 2. 打印日 ...
- iframe父子页面通信
一.同域下父子页面的通信 1.父页面调用子iframe页面 (1)通过iframe的Id获取子页面的dom,然后通过内置属性contentWindow取得子窗口的window对象,此方法兼容各个浏览器 ...
- O040、Migrate Instance 操作详解
参考https://www.cnblogs.com/CloudMan6/p/5538599.html Migrate 操作的作用是将instance 从当前的计算节点迁移到其他的计算节点上. ...
- python 列表字典按照字典中某个valu属性进行排序
对用户名进行排序 1. 直接上代码 base_dn_list = [ {', 'tenant': 'HAD', 'role': {'roleID': 'project', 'roleName': '项 ...
- nps内网渗透利用
0x00 前言 对比了比较多的代理工具,如ew流量不稳定,容易断:frsocks目前免杀,也是容易断.frp需要落地配置文件,不符合渗透的规则.reg正向的socks,速度比较慢,扫描是个问题.其实我 ...
- fastadmin html数字验证
<input id="c" name="row[q]" data-rule="required;range(0~)" class=&q ...
- 关于SYSLINUX的一些重要描述摘录
以下资源都来自官方文档,原文摘录 The SYSLINUX suite contains the following boot loaders ("derivatives"), f ...
- 使用busybox1.21.1制作根文件系统
1. 下载源码 https://busybox.net/downloads/ 2. 解压 3. 修改Makefile ~/busybox-1.21.1$ vi Makefile 164行: 修改前:C ...
- VM12及CentOS-6.10的安装
VM12的安装破解步骤 1:打开VMware 12安装界面后,点击[下一步]2:勾选[我接受许可协议中的条款]安装VMware Workstation 12 ,然后点击[下一步]3:修改默认安装路径, ...