校赛题解

猫猫虫的帮手

补题链接:https://www.luogu.com.cn/problem/T599530
我们记 \(sum = \sum_{i=1}^{n} a[i]\)。容易发现 \(p(i)=\frac{a[i]}{sum}\)。于是我们只要 \(O(logn)\) 求出 \(sum\) 逆元,然后线性求和即可。

const int N = 1e7 + 5;
const int mod = 998244353;
ll a[N], sum;
inline ll power(ll a, ll p) {
	ll ans = 1;
	for (; p; a = a * a % mod, p >>= 1) if (p & 1) ans = ans * a % mod;
	return ans;
}

signed main(void) {
	int n; ll k;
	read(n); read(k);
	for (int i = 1; i <= n; i++) {
		read(a[i]); sum += a[i];
	}
	ll inv = power(sum, mod - 2) % mod;
	ll ans = 0, now = k;
	for (int i = 1; i <= n; i++) {
		ans = (ans + now * a[i] % mod * inv % mod) % mod;
		now = now * k % mod;
	}
	writeln(ans);
    return 0;
}

猫猫虫的序列

补题链接:https://www.luogu.com.cn/problem/T599232
下面这个式子很容易从定义得出来:

\[a_n - a_{\left\lfloor\frac{n}{2}\right\rfloor} = \begin{cases} \ \ 1 & n \equiv 0 \ \text{或}\ n \equiv 3 \!\!\!\!\pmod{4} \\ -1 & n \equiv 1 \ \text{或}\ n \equiv 2 \!\!\!\!\pmod{4} \end{cases} \]

\(n\)的二进制表示为\(b(m)b(m-1)…b(0)\),且\(b(m)=1\),设\(p(n)\)\(b(i)=b(i+1)\)\(i\)个数,\(q(n)\)\(b(i)\neq b(i+1)\)\(i\)个数,则\(a(n)=|p(n)-q(n)|\)

我们考虑数位dp计算\(|p(n)-q(n)|\),设\(dp(i,j,x,y)\)表示前\(i\)位有\(j\)个,最后一位是\(x\),和\(n\)大小关系是\(y\)的方案数。

直接进行dp,复杂度为\(O(log^2 n)\)单询问,通过预处理优化下可以\(O(log n)\)每组询问,即可通过本题。

const int mod = 1e9 + 7;
const int S = 62;
ll T, n, ans, na, a[S + 5], jie[S + 10], nj[S + 10], yc[S + 10][S * 2 + 10];
inline void add(ll &x, ll y) {
	x += y;
	if (x >= mod)x -= mod;
}

inline ll qpow(ll x, ll y) {
	ll z = 1;
	while (y) {
		if (y % 2)z = x * z % mod;
		x = x * x % mod;
		y /= 2;
	}
	return z;
}

inline ll C(ll x, ll y) { return (jie[x] * nj[y] % mod) * nj[x - y] % mod; }

signed main(void) {
	jie[0] = 1;
	for (int i = 1; i <= S; i++) jie[i] = jie[i - 1] * i % mod;
	nj[S] = qpow(jie[S], mod - 2);
	for (int i = S - 1; i >= 0; i--) nj[i] = nj[i + 1] * (i + 1) % mod;
	for (int i = 1; i <= S; i++)
		for (int j = 0; j <= S * 2; j++)
			for (int k = 0; k < i; k++) add(yc[i][j], C(i - 1, k) * abs(j + k + k - i + 1 - S) % mod);
	for (read(T); T; T--) {
		read(n); na = 0; ans = 0;
		while (n) {
			a[++na] = n % 2;
			n /= 2;
		}
		for (int i = na - 1, k = S; i >= 1; i--) {
			add(ans, yc[i][S]);
			if (a[i] == 1) {
				add(ans, yc[i][k - 1 + (a[i] != a[i + 1]) * 2]);
			}
			k += -1 + (a[i] == a[i + 1]) * 2;
			if (i == 1) add(ans, abs(k - S));
		}
		writeln(ans);
	}
	//fwrite(pf, 1, o1 - pf, stdout);
	return 0;
}
posted @ 2025-04-21 18:39  EternalEpic  阅读(196)  评论(0)    收藏  举报