D - Pedometer
区间和A[r]-A[l-1] 为 k的倍数,转化为A[r]%k == A[l-1]%k, map统计一下前缀和和余数。
将数组开到二倍, 在后面的时候把前面的减去了,防止重复计算。
#define int long long
void solve()
{
int n, m;
cin >> n >> m;
vector<int> A(n * 2 + 1), B(n * 2 + 1);
for (int i = 1; i <= n; i++)
{
cin >> A[i];
A[i + n] = A[i];
}
for (int i = 1; i <= n * 2; i++)
B[i] = B[i - 1] + A[i];
map<int, int> D;
int ans = 0;
for (int i = 1; i <= n; i++)
{
int num = B[i] % m;
if (D.count(num))
ans += D[num];
D[num]++;
}
for (int j = n + 1, i = 1; j <= 2 * n; i++, j++)
{
int num1 = B[i] % m;
int num2 = B[j] % m;
D[num1]--;
if (D.count(num2))
{
ans += D[num2];
}
}
cout << ans;
}
E - Permute K times
考虑倍增,第j个数字在2^i后的位置
void solve()
{
int n, k;
cin >> n >> k;
vc<int> A(n);
vc<vc<int>> B(64, vc<int>(n));
for (int i = 0; i < n; i++)
{
int x;
cin >> x;
B[0][i] = --x;
}
for (auto &i : A)
cin >> i;
for (int i = 1; i < 64; i++)
for (int j = 0; j < n; j++)
B[i][j] = B[i - 1][B[i - 1][j]];
for (int i = 0; i < n; i++)
{
int pos = i;
for (int j = 0; j < 64; j++)
if (k & (1LL << j))
pos = B[j][pos];
cout << A[pos] << " ";
}
}
F - Rearrange Query
典题,但我不会,学到了。
LL mod = 1e9 + 7;
int P = 13331;
#define int long long
int h1[N], h2[N];
int ksm(int a, int b)
{
int res = 1;
while (b)
{
if (b & 1)
res = res * a % mod;
b >>= 1;
a = a * a % mod;
}
return res;
}
void solve()
{
int n, q;
cin >> n >> q;
for (int i = 1; i <= n; i++)
{
int x;
cin >> x;
h1[i] = (h1[i - 1] + ksm(P, x)) % mod;
}
for (int i = 1; i <= n; i++)
{
int x;
cin >> x;
h2[i] = (h2[i - 1] + ksm(P, x)) % mod;
}
while (q--)
{
int l, r, L, R;
cin >> l >> r >> L >> R;
if ((h1[r] - h1[l - 1] + mod) % mod == (h2[R] - h2[L - 1] + mod) % mod)
cout << "Yes" << endl;
else
cout << "No" << endl;
}
}