Каосар і Діагоналі#12260

Каосар і Діагоналі (Розбір)

Автор проблеми:

AlKaosar Hussain

Підготовлено:

AlKaosar Hussain

Редаговано:

Hasan Saleh (MathModel)

Рішення

Розглянемо впорядкований спосіб пар i<j, де \gcd(i,j)=1, це допомагає уникнути подвійного підрахунку, оскільки невпорядковані пари підраховуються двічі. Для деякого ми хочемо знати, скільки цілих чисел , менших за нього, таких що \gcd(i,j)=1, це еквівалентно Функція Ейлера. Оскільки ми не будемо підраховувати пару двічі таким чином, ми можемо підсумувати значення для кожного цілого числа окремо, формально

\displaystyle \sum_{i=1}^n \varphi(i)

Однак, якщо ви помітили графік, там вже є ліній, що формують графік. Отже,

Тому вираз буде

\displaystyle \left ( \sum_{i=1}^n \varphi(i) \right ) - n

Однак зверніть увагу, що ви підраховуєте \varphi(1)=1, тому ми повинні виключити його, отже, фінальний вираз буде

\displaystyle \left ( \sum_{i=1}^n \varphi(i) \right ) -n-1

Підрахувавши для всіх 1 \le x \le 2 \cdot 10^5, ми отримуємо \mathcal{O}(\sum n), однак з умови задачі не обмежена, тому ми можемо прискорити обчислення за допомогою префіксної суми.

\displaystyle \text{prefix}[x]=\text{prefix}[x-1]+\varphi(x)

Тепер ми можемо відповідати на набори входних даних за часу!.

Складність \mathcal{O}(N\log \log N), де N=2 \cdot 10^5.

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;

#define int long long
template<class T> using oset=tree<T,null_type,less<T>,rb_tree_tag,tree_order_statistics_node_update>;

const int N=200000;
int phi[N+1];
vector<int>sum={0};

void solve(){
    int n;cin>>n;
    cout<<sum[n]-n-1<<"\n";
}

signed main(){
    for(int i=1;i<=N;i++)phi[i]=i;
    for (int i=2;i<=N;i++) {
        if (phi[i]==i) {
            for (int j=i;j<=N;j+=i)
                phi[j]-=phi[j]/i;
        }
    }
    int cur=0LL;
    for(int i=1;i<=N;i++){
        cur+=phi[i];
        sum.push_back(cur);
    }
    int t=1;cin>>t;
    while(t--) solve();
}