JZOJ5439. Calculate

题目大意



\(A_i<=500\)而不是\(A_i<=1000\), 不过问题不大了

解题思路

考试的时候完全没有思路. 经验是看到这种数学题, 还是要从最初的式子入手, 寻找一些性质或者转化一下所求.

考虑化掉这个最难受的 \(\left \lfloor \frac{a-b}{c} \right \rfloor\):

\[\left \lfloor \frac{a-b}{c} \right \rfloor=\left \lfloor \frac{c*\left \lfloor \frac{a}{c} \right \rfloor + a \operatorname{mod} c -c*\left \lfloor \frac{b}{c} \right \rfloor - b \operatorname{mod} c}{c} \right \rfloor=\left \lfloor \frac{a}{c} \right \rfloor - \left \lfloor \frac{b}{c} \right \rfloor-[a \operatorname{mod} c < b \operatorname{mod} c] \]

代入呗

\[\sum^{n}_{i=1}\left \lfloor \frac{T}{A_i} \right \rfloor - \left \lfloor \frac{B_i}{A_i} \right \rfloor-[T \operatorname{mod} A_i < B_i \operatorname{mod} A_i] \]

\(A_i\)只有\(500\)种取值. 按照\(A_i\)分类以后, \(k \operatorname{mod} A_i\) 的取值也只有\(500\)种. 可以想到按照\(A_i\)分类以后, 预处理一些东西来处理.

预处理什么? \(\sum^n_{i=1} \left \lfloor \frac{B_i}{A_i} \right \rfloor\)\(B_i \operatorname{mod} A_i\)的余数的每一类的个数.

#include <cstdio>
#include <cstring>
#define M 510
#define N 100010
#define ll long long
#define init(a, b) memset(a, b, sizeof(a))
#define fo(i, a, b) for(int i = (a); i <= (b); ++i)
#define fd(i, a, b) for(int i = (a); i >= (b); --i)
using namespace std;
inline int read() // notice : 1. long long ? 2. negative ?
{
	int x = 0; char ch = getchar();
	while(ch < '0' || ch > '9')	ch = getchar();
	while(ch >= '0' && ch <= '9')	x = (x << 3) + (x << 1) + (ch ^ 48), ch = getchar();
	return x;
}
int n, q;
ll a[N], b[N], sum[M][M], p[M];
inline ll calc(int v)
{
	ll ret = 0;
	fo(i, 1, 500)	ret += v / i * sum[i][i] - (sum[i][i] - sum[i][v % i]) - p[i];
	return ret;
}
int main()
{
	freopen("calculate.in", "r", stdin);
	freopen("calculate.out", "w", stdout);
	for(int T = read(); T; --T)
	{
		init(sum, 0); init(p, 0);
		n = read(), q = read();
		fo(i, 1, n)	a[i] = read();
		fo(i, 1, n)	b[i] = read();
		fo(i, 1, n)	p[a[i]] += b[i] / a[i], ++sum[a[i]][b[i] % a[i]];
		fo(i, 1, 500)	fo(j, 1, i)	sum[i][j] += sum[i][j - 1];
		while(q--)
		{
			int op = read(), x = read();
			if(op == 1)
			{
				int y = read();
				p[a[x]] -= b[x] / a[x];
				fo(i, b[x] % a[x], a[x])	--sum[a[x]][i];
				p[y] += b[x] / y;
				fo(i, b[x] % y, y)	++sum[y][i];
				a[x] = y;
			}
			else if(op == 2)
			{
				int y = read();
				p[a[x]] += y / a[x] - b[x] / a[x];
				int l = y % a[x], r = b[x] % a[x], delta = 1;
				if(l > r){int t = l; l = r; r = t; delta = -1;}
				fd(i, r - 1, l)	sum[a[x]][i] += delta;
				b[x] = y;
			}
			else
			{
				int l = 0, r = 1000000000, ans = 1000000000;
				while(l <= r)
				{
					int mid = (l + r) >> 1;
					if(calc(mid) >= x)	r = (ans = mid) - 1;
					else l = mid + 1;
				}
				printf("%d\n", ans);
			}
		}
	}
	return 0;
}
posted @ 2021-03-10 19:13  Martin_MHT  阅读(56)  评论(0)    收藏  举报