首页 > 其他分享 >DTOJ-2537-J友-题解

DTOJ-2537-J友-题解

时间:2022-12-13 17:03:38浏览次数:42  
标签:frac int 题解 sum align res binom DTOJ 2537

题目链接

题目大意

求 \((0,0)\) 到 \((x,y)\) 走 \(n\) 步的方案数,对 \(P\) 取模(每步上下左右 \(1\) 格)

(\(x,y,n\le 10^6\),不保证 \(P\) 质数)

题解

法一

可以设向左的步数为 \(i\) 则向右的步数为 \(x+i\)

同理设向下的步数为 \(j\) 则向上的步数为 \(y+j\)

我们有 \(x+2i+y+2j=n\)

于是 \(j=\frac{n-x-y}{2}-i\)

方案数相当于一个多重集排列

多重集排列公式: \(\displaystyle\frac{n!}{m_1!m_2!\dots m_k!}\)

枚举 \(i\),得方案数

\[\begin{align*} &\sum_i\frac{n!}{i!(x+i)!j!(y+j)!}\\ =&\sum_i\frac{n!}{i!(x+i)!(\frac{n-x-y}{2}-i)!(\frac{n-x+y}{2}-i)!}\\ \end{align*} \]

注意到这个时候因为没有逆元不能直接做

我们继续推

\[\begin{align*} &\sum_i\frac{n!}{i!(x+i)!(\frac{n-x-y}{2}-i)!(\frac{n-x+y}{2}-i)!}\\ =&\sum_i\frac{\binom{(n-x-y)/{2}}{i}\binom{(n+x+y)/{2}}{x+i}n!}{((n-x-y)/2)!((n+x+y)/{2})!}\\ =&\binom{n}{(n+x+y)/{2}}\sum_i \binom{(n-x-y)/{2}}{i}\binom{(n+x+y)/{2}}{x+i} \end{align*} \]

这边需要用到个小公式

范德蒙德卷积:

\(\displaystyle{\sum_i{\binom{n}{i}\binom{m}{k-i}}=\binom{n+m}{k}}\)

组合意义:从 \(n+m\) 选 \(k\) 个,可以枚举在 \(n\) 个中选择 \(i\) 个,则 \(m\) 个中就选择 \(k-i\) 个

也就是说

\[\begin{align*} &\binom{n}{(n+x+y)/{2}}\sum_i \binom{(n-x-y)/{2}}{i}\binom{(n+x+y)/{2}}{x+i}\\ =&\binom{n}{(n+x+y)/{2}}\sum_i \binom{(n-x-y)/{2}}{i}\binom{(n+x+y)/{2}}{(n-x+y)/{2}-i}\\ =&\binom{n}{(n+x+y)/{2}}\binom{n}{(n-x+y)/2} \end{align*} \]

处理非质数模数的方法:

预处理所有数质因数分解,组合数直接处理每个指数幂

法二

坐标系转化

一个常见套路:

\((x,y)\rightarrow (x+y,x-y)\)

\((0,\pm1)\rightarrow(\pm1,\mp1)\)

\((\pm1,0)\rightarrow(\pm1,\pm1)\)

于是走 \(n\) 步可以拆成两个独立的方向,每个方向走 \(n\) 步

答案就可以直接出来是 \(\displaystyle{\binom{n}{(n+x+y)/{2}}\binom{n}{(n-x+y)/2}}\)

代码

#include <bits/stdc++.h>
#define ll long long
#define fs first
#define sc second
using namespace std;
const int N = 1e6+5;
int n,P,x,y;
map<int,int> a[N];
int qpw(int a, int b)
{
	int res=1;
	for(; b; b>>=1,a=(ll)a*a%P) if(b&1) res=(ll)a*res%P;
	return res;
}
int work(int m)
{
//	printf("m=%d\n",m);
	if(m<0 or n<m) return 0;
	map<int,int> res;
	for(int i=n; i>=(n-m+1); i--)
	{
		for(auto v:a[i])
		{
			if(res.count(v.fs)) res[v.fs]+=v.sc;
			else res.insert(v);
		}
	}
	for(int i=1; i<=m; i++)
	{
		for(auto v:a[i])
		{
			assert(res.count(v.fs)); 
			res[v.fs]-=v.sc;
		}
	}
	int ans=1;
	for(auto v:res) ans=(ll)ans*qpw(v.fs,v.sc)%P;
	return ans;
}
int main()
{
	scanf("%d%d%d%d",&n,&P,&x,&y);
	for(int i=2; i<=n; i++)
	{
		if(!a[i].size())
		{
			a[i].insert({i,1});
			for(int j=(i<<1); j<=n; j+=i)
			{
				int t=0;
				for(int u=i; u<=j; u*=i,t++) if(j%u) break;
				a[j].insert({i,t});
			}
		}
	}
//	for(int i=2; i<=n; i++) { for(auto v:a[i]) printf("(%d %d)",v.fs,v.sc); puts(""); }
	int A=n+x-y;
	if(A<0 or A&1) { puts("0"); return 0; }
	A>>=1; int B=A+y;
	int res=(ll)work(A)*work(B)%P;
	return !printf("%d\n",res);
}

标签:frac,int,题解,sum,align,res,binom,DTOJ,2537
From: https://www.cnblogs.com/copper-carbonate/p/16979272.html

相关文章

  • javascript中setInterval越来越快的问题解决方法
    vartimerfunctionrun(){ //clearInterval要放在方法开始,不然的话,下面的代码还没运行到clearInterval,又开始了循环了。if(timer){clearInter......
  • 问题解决系列:io.grpc.netty.shaded.io.netty.handler.ssl.NotSslRecordException_ not
    问题场景最近使用公司微服务框架开发后台,要调用由​​python​​​写的服务端接口。这里我们是使用了​​grpc​​​来做不同语言之间的接口调用。已知​​python​​服务端......
  • 洛谷 P5143 攀爬者 题解
    原题链接P5143攀爬者解析内心OS第一眼看上去:他**滴,这么离谱的公式,这还是正常的橙题吗?1分钟后······这么简单的题,还好意思当橙题?(请忽略上方内容)......
  • 「题解」洛谷 P8850 [JRKSJ R5] Jalapeno and Garlic
    2022.12upd:原先代码锅了,重写了一份。看上去是比较常规的题,应当需要更灵敏的直觉和更快的速度解决这道题。首先考虑若已经确定一个\(x\),那么贪心修改策略就是随便找一个......
  • 「题解」洛谷 P8848 [JRKSJ R5] 1-1 B
    首先不考虑只有\(1\)或者只有\(-1\)的平凡情况。令\(z\)为\(1\)的个数,\(f\)为\(-1\)的个数,若有\(f\geqz\),那么可以构造使得最大子段和为\(1\)(因为有\(1\)......
  • 【题解】P3153 [CQOI2009]跳舞
    原题链接[CQOI2009]跳舞题目描述一次舞会有\(n\)个男孩和\(n\)个女孩。每首曲子开始时,所有男孩和女孩恰好配成\(n\)对跳交谊舞。每个男孩都不会和同一个女孩跳两......
  • 怎么彻底解决Windows如何不进行更新——问题解决
    文章目录​​一、情况描述​​​​二、问题解决​​​​2.1方法一​​​​2.2方法二​​一、情况描述感觉最近一直在更新啊,如果一直不更新,就会没有关机选项,而更新的话,电......
  • 【题解】P2050 [NOI2012] 美食节
    [NOI2012]美食节题目描述CZ市为了欢迎全国各地的同学,特地举办了一场盛大的美食节。作为一个喜欢尝鲜的美食客,小M自然不愿意错过这场盛宴。他很快就尝遍了美食节所有......
  • 2022icpc杭州铜牌题题解
    A.ModuloRuinstheLegend\[求s、d,使\suma_i+sn+d\frac{n(n+1)}{2}\(\bmodm)最小\\设sum=\suma_i\(\bmodm),t=gcd(n,\frac{n(n+1)}{2})\\原式=sum+kt\(\bm......
  • Git merge 报错:* commits behind * branch 问题解决
    Git大家都用的很多,但是在多人开发中难免会遇到代码冲突问题,因为mergepullrequest的时候遇到很多次这个问题,所以今天特意来记录一下: 问题:在mergePR到主分支(master/......