首页 > 其他分享 >abc270

abc270

时间:2022-09-26 15:25:56浏览次数:43  
标签:right dfrac leq abc270 max modint left

\(\textbf{G.}\)

  • 当 \(a = 0\) 时有 \(x _ i = \begin{cases} s &, i = 0 \\ b &, i \geq 1 \end{cases}\). 所以可以 \(\mathcal{O}(1)\) 计算.
  • 当 \(a = 1\) 时有 \(x _ i = s + i b \bmod {p}\). 所以 \(i \equiv \dfrac{g - s}{b} \pmod{p}\), 可以 \(\mathcal{O}(1)\) 计算.
  • 当 \(a \geq 2\) 时有 \(x _ i + \dfrac{b}{a - 1} \equiv a \left( x _ {i - 1} + \dfrac{b}{a - 1} \right) \pmod{p}\). 所以 \(a ^ i \equiv \dfrac{g + \dfrac{b}{a - 1}}{s + \dfrac{b}{a - 1}} = \dfrac{(a - 1) g + b}{(a - 1) s + b} \pmod{p}\), 可以使用 BSGS 在 \(\mathcal{O}(\sqrt p)\) 内计算.

所以就做完了, 注意取模的细节问题. 单次复杂度 \(\mathcal{O}(\sqrt{p})\).

int bsgs(modint a, modint b){ /* 解方程 a ^ i = b */
	if(a.val() == 0 && b.val() == 0)
		return 1;
	if(a.val() == 0 && b.val() != 0){
		if(b.val() == 1)
			return 0;
		else
			return -1;
	}
	if(a.val() != 0 && b.val() == 0)
		return -1;

	const int S = sqrt(mod);
	map<int, int> mp;
	for(int i = 0; i < S; i ++)
		mp[(b * a.qpow(i)).val()] = i;
	for(int j = S; j <= mod - 1; j += S)
		if(mp.count(a.qpow(j).val()))
			return j - mp[a.qpow(j).val()];
	return -1;
}

void solve(){
	int A, B, S, G;
	cin >> mod >> A >> B >> S >> G;

	if(G == S){
		cout << 0 << "\n";
		return;
	}

	if(A == 0){
		if(S == G)
			cout << 0 << "\n";
		else if(G == B)
			cout << 1 << "\n";
		else
			cout << -1 << "\n";
		return;
	}

	if(A == 1){
		ll P = G - S;
		ll Q = B;
		ll R = __gcd(P, Q);
		P /= R, Q /= R;

		if(Q % mod == 0){
			cout << -1 << "\n";
			return;
		}
		cout << (modint(P) / modint(Q)).val() << "\n";
		return;
	}

	ll P = (ll)(A - 1) * G + B;
	ll Q = (ll)(A - 1) * S + B;
	ll R = __gcd(P, Q);
	P /= R, Q /= R;

	if(Q % mod == 0){
		cout << -1 << "\n";
		return;
	}

	cout << bsgs(modint(A), modint(P) / modint(Q)) << "\n";
}

\(\textbf{H.}\)

考虑对于当前的局面 \((b _ 1, \cdots, b _ n)\), 定义 \(k(b _ 1, \cdots, b _ n) = \max(\max(0, a _ i - b _ i) : 1 \leq i \leq n)\) 表示当前状态和终止状态的距离.

考虑设 \(f(k)\) 表示距离为 \(k\) 的状态期望需要多少步到达终止状态. 则 \(f(0) = 0\); 答案为 \(f(a _ n)\). 考虑转移:

  • 若选择 \(a _ i < k\) 的下标 \(i\). 那么得到状态的距离为 \(k' = \max (a _ i, \max(a _ j - b _ j - 1 : j \neq i)) = \max(a _ i, k - 1) = k - 1\).

    其中用到 \(\max(a _ j - b _ j - 1 : j \neq i) = \max(a _ j - b _ j : j \neq i) - 1\), 而对于 \(a _ i - b _ i < k\), 所以 \(\max(a _ j - b _ j : j \neq i) = k\).

  • 若选择 \(a _ i \geq k\) 的下标 \(i\). 那么得到状态的距离为 \(k' = \max (a _ i, \max(a _ j - b _ j - 1 : j \neq i)) = a _ i\).

    其中用到 \(\max(a _ j - b _ j - 1 : j \neq i) \leq \max(a _ j - b _ j - 1 : j) = k - 1 < a _ i\).

所以 \(f(k) = 1 + \dfrac{1}{n} \sum _ {i = 1} ^ {n} [a _ i < k] f(k - 1) + [a _ i \geq k] f(a _ i)\).

考虑设 \(a _ 1 \leq \cdots \leq a _ l < k \leq a _ {l + 1} \leq \cdots \leq a _ n\). 那么转移重写为 \(f(k) = 1 + \dfrac{l}{n} f(k - 1) + \dfrac{1}{n} \sum _ {i = l + 1} ^ {n} f(a _ i)\).

于是 \(f(k - 1) = \dfrac{1}{l} \left( n f(k) - n - \sum _ {i = l + 1} ^ {n} f(a _ i) \right)\).

用 \(k\) 替换 \(k - 1\) 得到 \(f(k) = \dfrac{1}{l} \left( n f(k + 1) - n - \sum _ {i = l + 1} ^ {n} f(a _ i) \right)\), 其中 \(a _ l \leq k < a _ {l + 1}\).

注意到此时边界为 \(f(0) = 0\); 答案为 \(f(a _ n)\). 这和转移的顺序不符合.

所以只需令 \(g(k) = f(a _ n) - f(k)\). 那么转移变为 \(g(k) = \dfrac{1}{l} \left( n g(k + 1) + n - \sum _ {i = l + 1} ^ {n} g(a _ i) \right)\); 边界为 \(g(a _ n) = 0\); 答案为 \(g(0)\).

直接计算预处理逆元和前缀和优化是 \(\mathcal{O}(n + V)\) 的. 考虑优化.

考虑固定 \(l\), 对于所有 \(a _ l \leq k < a _ {l + 1}\) 转移形式相同, 所以考虑设 \(G = \dfrac{n - \sum _ {i = l + 1} ^ {n} g(a _ i)}{l}\) 是定值.

那么 \(\begin{array}{l} g(a _ l) &= \dfrac{n}{l} g(a _ l + 1) - G = \dfrac{n}{l} \left( \dfrac{n}{l} g(a _ l + 2) - G \right) - G = \left( \dfrac{n}{l} \right) ^ 2 g(a _ l + 2) - G \left( 1 + \dfrac{n}{l} \right) \\ &= \cdots = \left( \dfrac{n}{l} \right) ^ {a _ {l + 1} - a _ l} g(a _ {l + 1}) - G \left( 1 + \dfrac{n}{l} + \cdots \left( \dfrac{n}{l} \right) ^ {a _ {l + 1} - a _ l - 1} \right) = \left( \dfrac{n}{l} \right) ^ {a _ {l + 1} - a _ l} g(a _ {l + 1}) - G \dfrac{1 - \left( \dfrac{n}{l} \right) ^ {a _ {l + 1} - a _ l}}{1 - \dfrac{n}{l}} \end{array}\).

于是每次只需依次计算 \(g(a _ {n - 1}), \cdots, g(a _ 1) = g(0)\) 即可. 使用前缀和优化即可做到 \(\mathcal{O}(n \log \mathrm{mod})\).

所以就做完了.

void solve(){
	int n;
	cin >> n;
	vector<ll> a(n + 1);
	for(int i = 1; i <= n; i ++)
		cin >> a[i];

	vector<modint> x(n + 1);
	x[n] = modint(0);
	modint S(0);
	for(int i = n - 1; i >= 1; i --){
		modint Y = (S - modint(n)) / modint(i);
		modint Z = modint(n) / modint(i);
		x[i] = Z.qpow(a[i + 1] - a[i]) * x[i + 1] - Y * (modint(1) - Z.qpow(a[i + 1] - a[i])) / (modint(1) - Z);
		S += x[i];
	}
	cout << x[1].val() << "\n";
}

标签:right,dfrac,leq,abc270,max,modint,left
From: https://www.cnblogs.com/zhangmj2008/p/abc270.html

相关文章

  • ABC270D(fake)
    ……你家E比D水……题意有$N$颗石子,每次可以拿$A_1$或$A_2$或……或$A_K$颗石子。Takahashi是先手,Snuke是后手。他们都想让自己取的石子数尽......