AT_abc172_e [ABC172E] NEQ 题解

前言

  • 事情是这样的,msjing在刷组合数取模的时候刷到了,思路想的挺快的,猛然发现luogu还可以交题解,为了抢社区贡献为了造福其他人,写一下吧
  • luogu
  • 直接粘吧

问题简述

  • 让你求方案数,保证单个数列中没有重复的数,并且两个数列同一个位置数不相同

solve

  • 对于没有重复的数的数列,我们要在 \(M\) 个数中选 \(N\) 个且不同,就是排列问题,答案为 \(A_M^N\)
  • 另一个问题,对于不能有相同位置的数,可以考虑错排
  • 等一等,这并不是传统的错排问题,因为并不是排 \(N\) 个而是排 \(M\)
  • 传统的错排我们有递推式 \(D_n = (n-1) \times (D_{n-1} + D_{n-2})\),我们可以对上述式子加一点东西
  • 我们发现会有 \(M - N\) 个数没有被选,所以我们加上这些数,那么递推式就变成了 \(D_n = (M - N) \times D_{n - 1} + (n-1) \times (D_{n-1} + D_{n-2})\)
  • 最终答案就是把上面两个乘起来

code

#include<bits/stdc++.h>
using namespace std;
constexpr int maxn=5e5+10,p=1e9+7;
int read() {int x=0,f=1;char ch=getchar();while (ch<'0' || ch>'9'){if (ch=='-') f=-1;ch=getchar();}while (ch>='0' && ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}
int n,m;
long long f[maxn],g[maxn];
long long ksm(long long x,long long y,long long mo)
{
	long long cnt=1;
	while(y)
	{
		if (y&1) cnt=(cnt*x)%mo;
		x=(x*x)%mo;
		y>>=1;
	}
	return cnt;
}
long long NY(long long a,long long p) {return ksm(a,p-2,p);}
void getfg(long long n)
{
	f[0]=g[0]=1;
	for (long long i=1;i<=n;i++) (f[i]=i*f[i-1])%=p,g[i]=NY(f[i],p);
}
long long getA(long long x,long long y) {return f[x]*g[x-y]%p;}
long long d[maxn];
void getD(long long n,long long m)
{
	d[0]=1,d[1]=m-n;
	for (long long i=2;i<=n;i++) (d[i]=(m-n)*d[i-1]%p+(i-1)*(d[i-1]+d[i-2])%p+p)%=p;
}
int main()
{
	n=read(),m=read();
	getfg(m);getD(n,m);
	printf("%lld\n",(d[n]*getA(m,n))%p);
	return 0;
}
  • 我就不打句号略略略
posted @ 2026-07-07 19:29  msjing  阅读(15)  评论(0)    收藏  举报