「ARC133E」Cyclic Medians 题解
本文网址:https://www.cnblogs.com/zsc985246/p/17513317.html ,转载请注明出处。
传送门
题目大意
给定 \(n,m,V,A\),你需要计算所有长为 \(n\)、值域为 \([1,V]\) 的整数序列 \(x\) 和长为 \(m\)、值域为 \([1,V]\) 的整数序列 \(y\) 形成的序列对 \((x_{1,2,\dots,n},y_{1,2,\dots,m})\) 的价值和。
序列对 \((x_{1,2,\dots,n},y_{1,2,\dots,m})\) 的价值由如下过程定义:
- 令 \(a=A\)。
- 从 \(0\) 到 \(nm-1\) 枚举 \(i\),每次让 \(a\) 变成 \((a,x_{(i \bmod n)+1},y_{(i \bmod m)+1})\) 的中位数。
- 价值为 \(a\) 最后的值。
答案对 \(998244353\) 取模。
\(1 \le n,m \le 2 \times 10^5,1 \le A \le V \le 2 \times 10^5\)。
思路
套路:枚举 \(i\),统计中位数 \(> i\) 的方案数,加起来就是所有方案的中位数的总和。
我们可以枚举 \(i\),然后将 \(x\) 和 \(y\) 中所有 \(> i\) 的数设为 \(1\),\(\le i\) 的数设为 \(0\),统计中位数 \(> i\) 的方案数。
现在一次操作 \((a,x,y)\) 只有三种情况:\((a,0,0),(a,1,1),(a,0,1)\)。
如果是 \((a,0,0)\),那么 \(0 \to a\),如果是 \((a,1,1)\),那么 \(1 \to a\),否则 \(a\) 不变。
发现如果有 \(x=y\) 的操作,那么 \(a\) 的值就与 \(A\) 无关了。
所以我们把有 \(x=y\) 操作的情况和无 \(x=y\) 操作的情况分开算。
对于有 \(x=y\) 操作的情况,显然最后一次 \(x=y\) 操作会决定 \(a\) 最终的结果。
所以我们只需要统计最后一次 \(x=y\) 操作满足 \(x=y=1\) 的方案。
我们发现,因为我们的 \(x\) 和 \(y\) 是任意取,所以在 \(k=t\) 时某次操作 \(x=y=0\) 的方案数与 \(k=V-t\) 时这次操作 \(x=y=1\) 的方案数相等。也就是说,方案具有对称性。
所以我们只需要用总方案 \(V^{n+m}\) 减去无 \(x=y\) 操作的方案数,然后除以 \(2\) 就是 \(x=y=1\) 的方案。
现在考虑无 \(x=y\) 操作的情况。
思考发现,如果 \(\gcd(n,m)=1\),那么每个数 \(p \in [1,n]\) 都会正好与每个 \(q \in [1,m]\) 组成一次 \((a,x_p,y_q)\) 数对。
进一步发现,如果 \(\gcd(n,m)=g\),那么一个数 \(p=i_1+gt_1,i_1 \in [0,g),t_1 \in [0,\frac{n}{g})\) 只可能与所有数 \(q=i_2+gt_2,i_2 \in [0,g),t_2 \in [0,\frac{m}{g})\) 组成数对。
所以必须满足 \(\forall p,q,x_p \neq y_q\)。
拆开其实就是三个条件:
- \(x_{i+g}=x_{i+2g}=\cdots=x_{i+(\frac{n}{g}-1)g}\);
- \(y_{i+g}=y_{i+2g}=\cdots=y_{i+(\frac{m}{g}-1)g}\);
- \(x_i \neq y_i\)。
那么分别计算 \((x_i,y_i)\) 取 \((0,1)\) 和 \((1,0)\),方案数为
因为 \(i \in [0,g)\),所以还需要再进行 \(g\) 次方。即
然后将两种情况的答案加起来就做完了。时间复杂度 \(O(V \log(n+m))\)。
代码实现
#include<bits/stdc++.h>
#define ll long long
#define For(i,a,b) for(ll i=(a);i<=(b);++i)
const ll N=1e6+10;
using namespace std;
const ll p=998244353;
ll ksm(ll a,ll b){ll bns=1;while(b){if(b&1)bns=bns*a%p;a=a*a%p;b>>=1;}return bns;}
ll n,m,k,A;
int main(){
scanf("%lld%lld%lld%lld",&n,&m,&k,&A);
ll ans=ksm(k,n+m);
ll g=__gcd(n,m);
For(i,1,k-1){
ll t=ksm((ksm(i,n/g)*ksm(k-i,m/g)+ksm(k-i,n/g)*ksm(i,m/g))%p,g);
if(A>i)ans=(ans+t)%p;
ans=(ans+(ksm(k,n+m)-t+p)*499122177)%p;//499122177是2在模998244353下的逆元
}
printf("%lld",ans);
return 0;
}
尾声
如果你发现了问题,你可以直接回复这篇题解
如果你有更好的想法,也可以直接回复!