ABC245Ex题解

前言

2024.11.21 联考第三题,本人由于太菜没有推出 m=px 的性质遂部分分跑路,作文以记之。

简要题意

对于一个长度为 n,值域为 [0,m1] 的序列 A,若 A 满足 ΠxAxres(modm) 则称 A 是好的。求好序列的方案数。

数据范围1n109,1resm1012

题解

因为联考时给了一些部分分,里面有一定的提示,所以难度小了很多。此题解大体按照部分分性质讲解。

基本情况

首先我们讨论 m=p,pprime 的情况。

如果这个时候 res=0,说明序列的乘积是 m 的倍数。但是 m 已经是一个质数,且序列中的数全部小于 m。这时只有当序列中有 0 存在时才对答案有贡献。稍加容斥,答案就是 mn(m1)n

如果 res 不为零,肯定不能选 0。我们其实可以先随便选择前 n1 个数,然后这前 n1 个数就可以确定最后一个数。证明一下:首先前 n1 个数的乘积取模后肯定在 [0,m1],令这个乘积为 x,然后因为 m 是质数,所以 x[0.m1] 倍在模 m 的意义下一定对应 [0,m1],且是一一对应的关系,所以可以唯一确定 An。所以这种情况方案数为 (m1)n1.

现在扩展一下,若 m=px,pprime 时我们又该如何计算方案?我们还是得分两种情况讨论。

拓展1

如果 res=0,说明序列的乘积得是 m 的倍数,换句话说也就是 px 的倍数。翻译一下,我们要让 A包含至少 xp,其他数在合法范围内随便选。然后因为 m1012,所以 x40。我们就可以容斥一下,转化成总方案数减去序列中少于 xp 的方案数。所以我们现在需要求解这样一个问题:

若我们钦定序列中有 ip,序列方案数。

问题转化

我们换一个视角,也就是把 ip 放入 n 个位置的方案数且同一位置可放多个也可以不放。这不就是把 i 个相同的球放入 n 个不同的盒子且盒子可为空吗?这就是一个很经典的组合数问题了,而且证明不重要故直接给出结论。方案数是 (n+i1n1),然后换一下变成 (n+i1i),于是就可以线性预处理了。

考虑完 p 的放置情况后我们还要考虑正常填数的方案。接下来的部分也就是笔者赛时没有想通的地方。对于一个位置 i,如果我已经放了一个 pci,是否就意味着这里不能继续填数了呢?答案是否定的。其实我只要选出一个数 t 满足 t×pci<m 就行,所以我们对于每一位都要考虑。因为填了一些 p 之后对现在选数只有范围的限制

知道这个有什么关系吗?就是你不用考虑一个位置是否填数,而是考虑填数的范围。这显然满足乘法原理。现在考虑范围,对于位置 i 已经填了 pci,我还能乘上哪些数?首先排除 p 的倍数,因为我已经把 p 填好了。所以我们填的一个数一定是 y×p+d,d[1,p) 的形式。然后我们填数还要满足小于 m,所以有 (y×p+d)×pci<px,把 pci 移项可得 y×p+d<pxci

翻译成人话就是我们选的数小于 pxci 且不为 p 的倍数。也许你会有疑问,ci 怎么处理?先别急,看到后面你就懂了。我们先关注 y×p+d 中的 y 取值范围,这显然是 [0,pxci1);然后 d 的范围前面提到过是 [1,p),所以位置 i 可以选择的方案就是 pxci1×(p1)。然后总方案就是把 n 个位置的方案乘起来:

i=1npxci1×(p1)

因为我钦定选了 ip,所以有 cj=i。当我们把上面的式子拆开时,就有:

pxncjn×(p1)n

然后你就发现所有 cj 全部加在了一起变成一个 i。于是问题最终的答案就是:

(n+i1i)×pxnni×(p1)n

解决了钦定有 ip 时的方案,我们就可以用总方案减去所有小于 x 时的方案就可以得到 res=0 的答案:

pxni<x(n+i1i)×pxnni×(p1)n

拓展2

然后讨论 res 不为 0 的情况,这个时候我们最多都选不到 xp 了。但是具体选多少还不好说。如果我把 res 拆一拆,写成 r×py 的形式,你是否会有一些想法呢?

考虑我们现在要在序列中选出恰好 yp,这样把等式两边的 py 抵消后就变成了基本情况中的第二种。我们恰好选 yp 的方案数是:

(n+y1y)×pxnny×(p1)n

但是考虑到序列的乘积只满足了 py 的倍数,所以还要去重。考虑如何去重。思路是用现在求得的总方案数乘合法概率。考虑现在的序列会得出些什么结果,写成集合是 {k×py|gcd(k,p)=1,k<pxy}。然后类比之前求位置选数的方案数的方法可得 pxy1×(p1)。考虑到如果我们已经确定了前 n1 个数后,最后一个数就已经唯一确定(原因与之前类似)。 然后因为如果把等式两边同时除以 py,两边的数都与 px 互质,所以在随机选数的情况下可以类比欧拉定理得出序列的乘积是均匀的。所以合法的概率就是 1pxy1×(p1),乘上总方案得到最终答案:

(n+y1y)×pxnxn+1×(p1)n1

拓展3

现在讨论一般情况。基于以上的内容,我们考虑将 m 写成 p1c1p2c2p3c3pkck 的形式。我们可以先求出所有 xAx(resmodpici)(modpici) 的方案数然后再乘法原理直接乘。可是为什么直接做是对的呢?

证明

假设对于每一个子问题我们已经找出任意一组合法解,我们把这些等式写成下面形式:

(xmodpici)(resmodpici)(modpici)

T=xmodpici,则我们现在就是在做中国剩余定理的合并。然后合并后的解一定合法,所以我们求出的任意一组解都可以合并,于是就直接乘起来即可。

代码

ll sol(ll rr, ll d, int x, ll mod){
	if(! rr){
		ll s = 0;
		for(int i = 0; i < x; ++i)s = (s + C[i] * qmi(d, x * n - n - i) % p * qmi(d - 1, n)) % p;
		return (qmi(mod, n) - s + p) % p;
	}
	int y = 0; while(rr % d == 0)rr /= d, ++y;
	return C[y] * qmi(d, x * n - n - x + 1) % p * qmi(d - 1, n - 1) % p;
}

ll ans = 1;

signed main(){
	freopen("equiv.in", "r", stdin);
	freopen("equiv.out", "w", stdout);
	n = rd(), r = rd(), m = rd(); C[0] = 1;
	for(int i = 1; i < 50; ++i)C[i] = C[i - 1] * (n + i - 1) % p * qmi(i, p - 2) % p;
	for(ll i = 2; i * i <= m; ++i)if(m % i == 0){
		int c = 0; ll x = 1; while(m % i == 0) m /= i, x *= i, ++c;
		ans = ans * sol(r % x, i, c, x) % p;
	}
	if(m > 1)ans = ans * sol(r % m, m, 1, m) % p;
	wt(ans);
	return 0;
}
posted @   Lyrella  阅读(12)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示