26.10.4qbxt集训day4

T1

image
直接数位dp。

点击查看代码
#include <iostream>
#include <algorithm>

using std::cin;
using std::cout;
const int N = 60;
typedef long long ll;

int a[50];
ll f[N][2][2][5][2]; // 第i位,不在/在前导,顶,j个当前的,填的是l 

int main()
{
	ll n;
	cin >> n;
	int cnt = 0;
	while (n)
	{
		a[++cnt] = n % 2;
		n /= 2;
	}
	std::reverse(a + 1, a + cnt + 1);
	f[0][1][1][0][0] = 1;
	for (int i = 1; i <= cnt; ++i)
	{
		if (i == 1)
			f[i][0][0][0][0] = f[i][0][0][0][0] + f[i - 1][1][1][0][0];
		else
			f[i][0][0][0][0] = f[i][0][0][0][0] + f[i - 1][0][0][0][0];
		// 不顶 1
		for (int j = 0; j <= 1; ++j)
		{
			for (int k = 0; k <= 0; ++k)
			{
				for (int x = 0; x <= 2; ++x)
					f[i][1][0][1][1] += f[i - 1][j][k][x][0];
			}
		}
		f[i][1][0][2][1] += f[i - 1][1][0][1][1];
		// 0
		for (int j = 1; j <= 1; ++j)
		{
			for (int k = 0; k <= a[i]; ++k)
			{
				for (int x = 0; x <= 2; ++x)
					f[i][1][0][1][0] += f[i - 1][j][k][x][1];
			}
		}
		if (a[i])
			f[i][1][0][2][0] += f[i - 1][1][1][1][0] + f[i - 1][1][0][1][0];
		else
			f[i][1][0][2][0] += f[i - 1][1][0][1][0];
		// 顶
		if (a[i])
		{
			for (int j = 0; j <= 1; ++j)
			{
				for (int x = 0; x <= 2; ++x)
					f[i][1][1][1][1] += f[i - 1][j][1][x][0];
			}
			f[i][1][1][2][1] += f[i - 1][1][1][1][1];
		}
		else
		{
			for (int j = 0; j <= 1; ++j)
			{
				for (int x = 0; x <= 2; ++x)
					f[i][1][1][1][0] += f[i - 1][j][1][x][1];
			}
			f[i][1][1][2][0] += f[i - 1][1][1][1][0];
		}
	}
	ll ans = 0;
	for (int j = 0; j <= 1; ++j)
	{
		for (int k = 0; k <= 1; ++k)
		{
			for (int x = 1; x <= 2; ++x)
				ans += f[cnt][1][j][x][k];
		}
	}
	cout << ans << '\n';
	return 0;
}

T2

image
用 \(b\) 表示 \(a\),发现 \(b - n\) 一定是 \(n^2\) 的因数,再想一想就会发现只需要统计 \(n^2\) 的 \(<n\) 的因数个数即可。

点击查看代码
#include <iostream>

using std::cin;
using std::cout;
const int N = 1e6 + 10;
typedef long long ll;

int tot;
int k;
int cnt;
int p[N];
int c[N];

void dfs(int x, ll now)
{
	if (x == tot + 1)
	{
		cnt++;
		return;
	}
	ll mul = 1;
	for (int i = 0; i <= c[x]; ++i)
	{
		if (now * mul < k)
			dfs(x + 1, now * mul);
		if (i != c[x])
			mul *= p[x];
	}
}

int main()
{
	int t;
	cin >> t;
	while (t--)
	{
		cnt = 0;
		for (int i = 1; i <= tot; ++i)
			c[i] = p[i] = 0;
		tot = 0;
		int n;
		cin >> n;
		if (n == 1)
		{
			cout << 0 << '\n';
			continue;
		}
		int x = n;
		for (int i = 2; i * i <= x; ++i)
		{
			if (!(x % i))
			{
				p[++tot] = i;
				while (!(x % i))
				{
					c[tot]++;
					x /= i;
				}
			}
		}
		if (x > 1)
			p[++tot] = x, c[tot] = 1;
		for (int i = 1; i <= tot; ++i)
			c[i] <<= 1;
		k = n;
		dfs(1, 1);
		cout << cnt << '\n';
	}
	return 0;
}

T3

推一推式子即可。

点击查看代码
#include <iostream>
#define pc putchar

using std::cin;
using std::cout;
const int mod = 998244353;
const int N = 1e6 + 10;

int n, k;
char c[4];
int f[N];
int g[N];

void print(int n, int d, int k, int opt)
{
	if (n == 0)
		return;
	if (opt == 0) // f
	{
		if (k <= f[n - 1])
			print(n - 1, d, k, 0);
		else if (k == f[n - 1] + 1)
		{
			print(n - 1, d, f[n - 1], 0);
			pc(c[d]);
		}
		else if (k <= f[n - 1] + 1 + g[n - 1])
		{
			print(n - 1, d, f[n - 1], 0);
			pc(c[d]);
			print(n - 1, (d + 1) % 3 + 1, k - f[n - 1] - 1, 1);
		}
		else if (k == f[n - 1] + 1 + g[n - 1] + 1)
		{
			print(n - 1, d, f[n - 1], 0);
			pc(c[d]);
			print(n - 1, (d + 1) % 3 + 1, g[n - 1], 1);
			pc(c[d % 3 + 1]);
		}
		else
		{
			print(n - 1, d, f[n - 1], 0);
			pc(c[d]);
			print(n - 1, (d + 1) % 3 + 1, g[n - 1], 1);
			pc(c[d % 3 + 1]);
			print(n - 1, d, k - f[n - 1] - 1 - g[n - 1] - 1, 0);
		}
	}
	else // g
	{
		if (k <= f[n - 1])
			print(n - 1, d, k, 0);
		else
		{
			print(n - 1, d, f[n - 1], 0);
			pc(c[d]);
			if (k > f[n - 1] + 1)
				print(n - 1, (d + 1) % 3 + 1, k - f[n - 1] - 1, 0);
		}
	}
}

int main()
{
	c[1] = 'A', c[2] = 'B', c[3] = 'C';
	cin >> n >> k;
	int p = -1;
	for (int i = 1; i <= n; ++i)
	{
		f[i] = ((f[i - 1] << 1) % mod + 2 + g[i - 1]) % mod;
		g[i] = ((f[i - 1] << 1) % mod + 1) % mod;
		if (f[i] >= k && p == -1)
			p = i;
	}
	cout << f[n] << '\n';
	if (p == -1)
		print(n, 1, f[n], 0);
	else
		print(p, 1, k, 0);
	return 0;
}

T4

image
注意到可以转换成二维数点,即可。
对于三个点对 \(i<j<k\),枚举 \(i\),找出对于 \(i\) 满足要求的最大 \(j\) 和最小 \(k\),随着 \(i\) 增大,最大的 \(j\) 一定单调不降,我们就把对于 \(j\) 合法的右射线在环上对应的区间加到树状数组里,再查询 \(i\) 的 \(k\) 端点到 \(4n\) 这个区间与区间内的区间的交的和即可。

点击查看代码
#include <iostream>
#define lowbit(x) x & (-x)

using std::cin;
using std::cout;
const int N = 1.5e6 + 10;
typedef long long ll;
struct Node
{
	ll x, y;
	friend Node operator-(const Node &a, const Node &b)
	{
		return (Node){a.x - b.x, a.y - b.y};
	}
	friend Node operator+(const Node &a, const Node &b)
	{
		return (Node){a.x + b.x, a.y + b.y};
	}
	friend ll operator*(const Node &a, const Node &b)
	{
		return a.y * b.x - a.x * b.y;
	}
};

int n, m;
int mn[N << 2];
int mx[N << 2];
Node info[N << 2];
Node p[N];
Node v[N << 2];

void add(int x, Node k)
{
	for (; x <= (n << 2); x += lowbit(x))
		info[x] = info[x] + k;
}
void add(int l, int r, int k)
{
	if (l > r)
		return;
	add(l - 1, (Node){k, -1ll * (l - 1) * k});
	add(r, (Node){-k, 1ll * r * k});
}
Node query(int x)
{
	Node ret = (Node){0, 0};
	for (; x; x -= lowbit(x))
		ret = ret + info[x];
	return ret;
}
ll query(int l, int r)
{
	if (l > r)
		return 0;
	Node q = query(r) - query(l - 1);
	return q.y + q.x * (l - 1);
}

int main()
{
	cin >> n >> m;
	for (int i = 1; i <= (n << 2); ++i)
	{
		if (i <= n)
			v[i] = (Node){i - 1, 0};
		else if (i <= (n << 1))
			v[i] = (Node){n, i % (n + 1)};
		else if (i <= (n << 1) + n)
			v[i] = (Node){n - i % ((n << 1) + 1), n};
		else
			v[i] = (Node){0, n - i % ((n << 1) + n + 1)};
	}
	for (int i = 1; i <= m; ++i)
		cin >> p[i].x >> p[i].y;
	for (int i = 1; i <= (n << 2); ++i)
	{
		Node a = p[1], b = p[1];
		for (int j = 2; j <= m; ++j)
		{
			if ((a - v[i]) * (p[j] - v[i]) > 0)
				a = p[j];
			if ((p[j] - v[i]) * (b - v[i]) > 0)
				b = p[j];
		}
		int l = i, r = (n << 2);
		int mid;
		while (l <= r)
		{
			mid = (l + r) >> 1;
			if ((a - v[i]) * (v[mid] - v[i]) >= 0)
			{
				mn[i] = mid;
				l = mid + 1;
			}
			else
				r = mid - 1;
		}
		l = i + 1, r = (n << 2);
		mx[i] = -1;
		while (l <= r)
		{
			mid = (l + r) >> 1;
			if ((v[mid] - v[i]) * (b - v[i]) >= 0)
			{
				mx[i] = mid;
				r = mid - 1;
			}
			else
				l = mid + 1;
		}
	}
	ll ans = 0;
	for (int i = 1, j = 1; i <= (n << 2); ++i)
	{
		if (j > i)
			add(i + 1, mn[i], -1);
		for (; j <= mn[i]; ++j)
		{
			if (j > i)
				add(j + 1, mn[j], 1);
		}
		if (mx[i] != -1)
			ans += query(mx[i], n << 2);
	}
	cout << ans << '\n';
	return 0;
}

讲的题:
https://files.cnblogs.com/files/blogs/832279/Dl1.zip?t=1791182204&download=true

posted @ 2026-10-04 13:35  SigmaToT  阅读(17)  评论(0)    收藏  举报