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;
}
浙公网安备 33010602011771号