AtCoder Beginner Contest 270 G,Ex

y1s1,G和Ex在推等比数列式子上是相似的。

G
前置知识:BSGS(其实就是根号讨论)

首先我们展开这个递归式:

\[X_{i}\equiv A^{i} S+\sum_{j=0}^{i-1} A^j B \mod P \]

感觉第一项有些难搞,故我们设\(F_{i}\),为:

\[F_{i}\equiv A^{i+1} S+\sum_{j=0}^{i} A^j B \mod P \]

之后我们套用BSGS的方法,设答案为\(kx+b\)

则:

\[F_{kx+b}=A^{kx+b+1} S+\sum_{j=0}^{kx+b} A^j B=A^{kx} \cdot A^{b+1} S+\sum_{j=0}^{kx} A^j B+A^{kx}\sum_{j=1}^{b} A^j B \]

提取公因式:

\[F_{kx+b}=A^{kx} ( A^{b+1} S+\sum_{j=1}^{b} A^j B)+\sum_{j=0}^{kx} A^j B \]

我们先进行预处理:枚举\(i=0\)\(\kappa -1\),将 \(A^{i+1} S+\sum_{j=1}^{i} A^j B\)\(P\)的值存入map中,如果已经在map中有这个值了,那么我们取\(i\)最小的(因为我们要让答案最小)。

之后枚举\(x\),查询\(\frac{G-\sum_{j=0}^{\kappa x} A^j B}{A^{\kappa x}} \mod P\)是否在map中,如果在,更新答案\(ans=\min (ans,\kappa x+C)\),其中\(C\)是map中预处理得到的最小的值。

若我们设\(\kappa =70000\),时间复杂度最优,大概是\(O(\sqrt n\log n)\)

Ex
一道好题。

首先\(n\)个计数器是不好记录状态的。

一、简化并列出状态

我们设状态\(k=\max(A_{i}-C_{i})\),其中\(C_{i}\)是第\(i\)个计数器的值。

可以发现,若\(k\leq 0\),则我们就满足了\(C_{i}\geq A_{i}\),并且,其实我们\(k\)在每次操作最多减去\(1\),故当\(k=0\)时,我们就终止操作。

这样有什么好处呢?

转移是更方便的:

我们设\(r\),满足\(A_{r}< k\leq A_{r+1}\),则:

  1. 如果我们将第\(i\)个计数器清零,且\(i\leq r\),那么\(k=k-1\)。(因为\(A_{i}\)<k,\(A_{i}-C_{i}\)也一定不超过\(k\),此时\(k\)只能是由\(j>r\)\(A_{j}-C_{j}\)转移而来)

  2. 如果我们将第\(i\)个计数器清零,且\(i > r\),那么\(k=A_{i}\)。 (因为\(A_{i}\)>k,将第\(i\)个计数器清零后\(A_{i}-C_{i}=A_{i}>k\),故此时\(k=A_{i}\)

至此,我们发现\(k=\max(A_{i}-C_{i})\),不仅减少状态数,并且转移还是简单的。

我们可以列出DP方程:\(F(k)\)表示状态为\(k\)时的期望操作次数,则\(F(k)=\frac{r}{n} F(k-1) + \frac{1}{n} \sum _{i=r+1}^{n} F(A_{i}) + 1\)\(F(MAX=A_{n})=0\)容易发现,这个转移是有环的。

二、处理转移有环的问题

我首先感觉这题和 https://atcoder.jp/contests/abc189/tasks/abc189_f 是类似的,设\(F(k)=K(k)F(MAX)+B(k)\)不过没继续往下想。

这题题解有一个非常巧妙的“移项去环”的方法:

我们将两侧乘上\(-1\)

\[-F(k)=\frac{r}{n}( -F(k-1) )+ \frac{1}{n} \sum _{i=r+1}^{n} (-F(A_{i})) - 1 \]

两边同时加上\(F(MAX)\)

\[F(MAX)-F(k)=\frac{r}{n}( F(MAX)-F(k-1) )+ \frac{1}{n} \sum _{i=r+1}^{n} (F(MAX)-F(A_{i})) - 1 \]

\(P(k)=F(MAX)-F(k)\),则:

\[P(k)=\frac{r}{n} P(k-1)+\frac{1}{n} \sum _{i=r+1}^{n} P(A_{i}) - 1 \]

\(P(k-1)\)移到左边,\(P(k)\)移到右边:

\[P(k-1)=\frac{n}{r} P(k)-\frac{1}{r} \sum _{i=r+1}^{n} P(A_{i}) + \frac{n}{r} \]

即:

\[P(k)=\frac{n}{r} P(k+1)-\frac{1}{r} \sum _{i=r+1}^{n} P(A_{i}) + \frac{n}{r} \]

此时,我们发现,右侧的每个下标都大于左侧,那么这个转移是可行的。

并且最终答案是\(F(MAX)=F(MAX)-F(0)=P(0)\)

时间复杂度为\(O(MAX)\)\(O(MAX\log MOD)\),TLE,怎么办?

三、优化

我们发现,对于\(k=a_{i}\)\(k=a_{i+1}-1\),时,\(r=i\)。(注意我们将下标统一\(+1\)了,现在的\(r\)其实是\(k+1\)时刻的\(r\))那么转移的系数、常数都是相同的。

重设\(P(i)\)\(k=a_{i}\)时的\(P\)

\(\alpha=\frac{n}{i},\beta=-\frac{1}{i} \sum _{j=i+1}^{n} P(A_{j}) + \frac{n}{i}, \theta=P(i+1),\delta=a_{i+1}-a_{i}\),则类似之前的G题,将递推式展开:

\[P(i)=\beta ^{\delta} \theta + \sum_{i=0}^{\delta-1} \beta ^{i} \alpha \]

前面是一个快速幂,后面是一个等比数列,可以在\(\log MOD+\log MAX\)的时间复杂度内求出。

由于题中保证\(A_{1}=0\),故答案等于\(P(1)\)

注意\(\delta=0\)的情况\(P(i)=P(i+1)=\theta\)

总时间复杂度为\(O(n \log MOD+n \log MAX)\)

代码:

#include<bits/stdc++.h>
#define debug(...) std::cerr<<#__VA_ARGS__<<" : "<<__VA_ARGS__<<std::endl

using ll=long long;

const int maxn=200005;
const ll mod=998244353;

ll n,sum,a[maxn],P[maxn];

ll qpow(ll x,ll y) {
	if(y==0ll) return 1ll;
	ll ret=qpow(x,y>>1ll);
	ret=ret*ret%mod;
	if(y&1ll) ret=ret*x%mod;
	return ret;
}

int main() {
	scanf("%lld",&n);
	for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
	//P[n]=0 and P[1] is the answer (P[i]=F[a[n]]-F[a[i]])
	for(int i=n-1;i>=1;i--) {
		ll alpha=n*qpow(i,mod-2ll)%mod;
		ll beta=(n-sum+mod)%mod*qpow(i,mod-2ll)%mod;
		ll theta=P[i+1];
		ll delta=a[i+1]-a[i];
		if(delta==0) P[i]=theta;
		else P[i]=(theta*qpow(alpha,delta)%mod+(1-qpow(alpha,delta)+mod)%mod*qpow((1-alpha+mod)%mod,mod-2ll)%mod*beta%mod)%mod;
		(sum+=P[i])%=mod;
	}
	printf("%lld\n",P[1]);
	return 0;
}
posted @ 2022-09-27 10:48  Nastia  阅读(67)  评论(0)    收藏  举报