Как я могу решить это с помощью BIT?

Я нашел хорошую математическую задачу, но все еще не могу ее решить, я попытался найти одно решение с помощью Google и обнаружил, что это можно решить с помощью структуры данных Binary Indexed Tree, но решение мне не ясно.

Вот проблема под названием «Поиск магических тройняшек», ее можно найти в онлайн-суде по Uva:

(a + b ^ 2) mod k = c ^ 3 mod k, где a<= Ь<= с и 1 <= а, б, в <= п.

учитывая п и к (1 <= n, k <= 10 ^ 5), сколько разных магических триплетов существует для известных значений n и k. Триплет отличается от другого, если любое из трех значений не одинаково в обоих триплетах.

и вот решение, которое я нашел:

#include <cstdio>
#include <cstring>
using namespace std;

typedef long long int64;

const int MAX_K = (int)(1e5);

int N, K;

struct BinaryIndexedTree{

typedef int64 bit_t;

static const int MAX_BIT = 3*MAX_K + 1;
bit_t data[MAX_BIT+1];
int SIZE;

void init(int size){
memset(data, 0, sizeof(data));
SIZE = size;
}

bit_t sum(int n){
bit_t ret = 0;
for(;n;n-=n&-n){
ret += data[n];
}
return ret;
}

bit_t sum(int from, int to){
return sum(to)-sum(from);
}

void add(int n, bit_t x){
for(n++;n<=SIZE;n+=n&-n){
data[n]+=x;
}
}
};

BinaryIndexedTree bitree;void init(){
scanf("%d%d", &N, &K);
}

int64 solve(){
bitree.init(2*K+1);

int64 ans = 0;
for(int64 i=N; i>=1; i--){
int64 b = i * i % K, c = i * i * i % K;
bitree.add(c, 1);
bitree.add(c+K, 1);
bitree.add(c+2*K, 1);
int64 len = i;
if(len >= K){
ans += (len / K) * bitree.sum(K);
len %= K;
}
if(len > 0){
ans += bitree.sum(b + 1, b + len + 1);
}
}

return ans;
}

int main(){
int T;
scanf("%d", &T);
for(int i=0; i<T; i++){
init();
printf("Case %d: %lld\n", i+1, solve());
}

return 0;
}

2

Решение

Вы полны решимости использовать биты? Я бы подумал, что обычные массивы подойдут. Я бы начал с создания трех массивов размера k, где arrayA [i] = количество значений a в диапазоне, равном i mod k, arrayB [i] = количество значений b в диапазоне, где b ^ 2 = i mod k и arrayC [i] = количество значений c в диапазоне, где c ^ 3 = i mod k. N и k оба <= 10 ^ 5, чтобы вы могли просто рассмотреть каждое значение a по очереди, b по очереди и c по очереди, хотя вы можете быть умнее, если k намного меньше, чем n, потому что это будет своего рода нечеткое выражение для подсчета столбов это позволяет вам определить, сколько чисел в диапазоне 0..n равно i mod k для каждого i.

Учитывая эти три массива, рассмотрим каждую возможную пару чисел i, j, где 0<= I, J < k и выяснить, что есть пары arrayA [i] * arrayB [j], которые имеют эти значения mod k. Суммируйте их в массиве AB [i + j mod k], чтобы найти количество способов, которыми вы можете выбрать a + b ^ 2 mod k = x для 0<= х < к. Теперь у вас есть два массива arrayAB и arrayC, где arrayAB [i] * arrayC [i] — это число способов найти тройку, где a + b ^ 2 = c ^ 3] = i, так что суммируйте это по всем 0<= я < K, чтобы получить ваш ответ.

1

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector