Когда алгоритм может иметь сложность квадратного корня(n)?
может кто-нибудь дать мне пример алгоритма, который имеет квадратный корень(N) сложность времени. Что вообще означает сложность времени квадратного корня?
3 ответов
- сложность времени квадратного корня означает, что алгоритм требует
O(N^(1/2))
оценки, где размер входного сигнала N. - в качестве примера для алгоритма, который принимает
O(sqrt(n))
время, алгоритм Гровера-это тот, который занимает столько времени. алгоритм Гровера - квантовый алгоритм поиска несортированной базы данных из n записей в
есть много случаев. Это несколько проблем, которые могут быть решены в корневой(n) сложности [лучше также возможно].
- найти, является ли число простым или нет.
- алгоритм Гровера: позволяет искать (в квантовом контексте) на несортированном входе во времени, пропорциональном квадратному корню размера входа.ссылке
- факторизация числа.
есть много проблем, с которыми вы столкнетесь, которые будут требовать использования сложности.
как ответ на вторую часть:
сложность sqrt(n) означает if the input size to your algorithm is n then there approximately sqrt(n) basic operations ( like **comparison** in case of sorting). Then we can say that the algorithm has sqrt(n) time complexity.
давайте проанализируем 3-ю проблему, и она будет ясна.
let's n= positive integer. Now there exists 2 positive integer x and y such that
x*y=n;
Now we know that whatever be the value of x and y one of them will be less than sqrt(n). As if both are greater than sqrt(n)
x>sqrt(n) y>sqrt(n) then x*y>sqrt(n)*sqrt(n) => n>n--->contradiction.
поэтому, если мы проверим 2 на sqrt ( n), то мы будем иметь все рассмотренные факторы (1 и n-тривиальные факторы).
фрагмент кода:
int n;
cin>>n;
print 1,n;
for(int i=2;i<=sqrt(n);i++) // or for(int i=2;i*i<=n;i++)
if((n%i)==0)
cout<<i<<" ";
Примечание: вы можете подумать, что не учитывая дубликат мы можем также достигните вышеуказанного поведения путем зацикливания от 1 до n. Да, это возможно, но кто хочет запустить программу, которая может работать в O(sqrt(n)) в O(n).. Мы всегда ищем лучшего.
пройдите через книгу Кормена введение в алгоритмы.
Я также попрошу вас прочитать следующий вопрос stackoverflow и ответы, которые они очистят все сомнения наверняка:)
простые числа
Как упоминалось в некоторых других ответах, некоторые основные вещи, связанные с простыми числами, занимают O(sqrt (n)) время:
- найти количество делителей
- найти сумму делителей
- найти totient
ниже я упоминаю два продвинутых алгоритма, которые также несут термин sqrt(n) по своей сложности.
МО
попробовать эту проблему: мощный блок
мое решение:
#include <bits/stdc++.h>
using namespace std;
const int N = 1E6 + 10, k = 500;
struct node {
int l, r, id;
bool operator<(const node &a) {
if(l / k == a.l / k) return r < a.r;
else return l < a.l;
}
} q[N];
long long a[N], cnt[N], ans[N], cur_count;
void add(int pos) {
cur_count += a[pos] * cnt[a[pos]];
++cnt[a[pos]];
cur_count += a[pos] * cnt[a[pos]];
}
void rm(int pos) {
cur_count -= a[pos] * cnt[a[pos]];
--cnt[a[pos]];
cur_count -= a[pos] * cnt[a[pos]];
}
int main() {
int n, t;
cin >> n >> t;
for(int i = 1; i <= n; i++) {
cin >> a[i];
}
for(int i = 0; i < t; i++) {
cin >> q[i].l >> q[i].r;
q[i].id = i;
}
sort(q, q + t);
memset(cnt, 0, sizeof(cnt));
memset(ans, 0, sizeof(ans));
int curl(0), curr(0), l, r;
for(int i = 0; i < t; i++) {
l = q[i].l;
r = q[i].r;
/* This part takes O(n * sqrt(n)) time */
while(curl < l)
rm(curl++);
while(curl > l)
add(--curl);
while(curr > r)
rm(curr--);
while(curr < r)
add(++curr);
ans[q[i].id] = cur_count;
}
for(int i = 0; i < t; i++) {
cout << ans[i] << '\n';
}
return 0;
}
Буферизация Запросов
попробовать эту проблему: запросы к дереву
мое решение:
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10, k = 333;
vector<int> t[N], ht;
int tm_, h[N], st[N], nd[N];
inline int hei(int v, int p) {
for(int ch: t[v]) {
if(ch != p) {
h[ch] = h[v] + 1;
hei(ch, v);
}
}
}
inline void tour(int v, int p) {
st[v] = tm_++;
ht.push_back(h[v]);
for(int ch: t[v]) {
if(ch != p) {
tour(ch, v);
}
}
ht.push_back(h[v]);
nd[v] = tm_++;
}
int n, tc[N];
vector<int> loc[N];
long long balance[N];
vector<pair<long long,long long>> buf;
inline long long cbal(int v, int p) {
long long ans = balance[h[v]];
for(int ch: t[v]) {
if(ch != p) {
ans += cbal(ch, v);
}
}
tc[v] += ans;
return ans;
}
inline void bal() {
memset(balance, 0, sizeof(balance));
for(auto arg: buf) {
balance[arg.first] += arg.second;
}
buf.clear();
cbal(1,1);
}
int main() {
int q;
cin >> n >> q;
for(int i = 1; i < n; i++) {
int x, y; cin >> x >> y;
t[x].push_back(y); t[y].push_back(x);
}
hei(1,1);
tour(1,1);
for(int i = 0; i < ht.size(); i++) {
loc[ht[i]].push_back(i);
}
vector<int>::iterator lo, hi;
int x, y, type;
for(int i = 0; i < q; i++) {
cin >> type;
if(type == 1) {
cin >> x >> y;
buf.push_back(make_pair(x,y));
}
else if(type == 2) {
cin >> x;
long long ans(0);
for(auto arg: buf) {
hi = upper_bound(loc[arg.first].begin(), loc[arg.first].end(), nd[x]);
lo = lower_bound(loc[arg.first].begin(), loc[arg.first].end(), st[x]);
ans += arg.second * (hi - lo);
}
cout << tc[x] + ans/2 << '\n';
}
else assert(0);
if(i % k == 0) bal();
}
}