牛客练习赛77 部分题解

比赛链接

A  小G的sum

牛客练习赛77  部分题解的最小的约数是牛客练习赛77  部分题解牛客练习赛77  部分题解的最大的约数是牛客练习赛77  部分题解

#include<bits/stdc++.h>
using namespace std ;
int main()
{
    std::ios::sync_with_stdio(false) , cin.tie(0) ;
    int n ;
    cin >> n ;
    long long ans1 = n ;
    long long ans2 = 1ll * n * (n + 1) / 2 ;
    cout << ans1 + ans2 << '\n' ;
    return 0 ;
}

 
B  小G的GCD

牛客练习赛77  部分题解

#include<bits/stdc++.h>
using namespace std ;
int main()
{
    std::ios::sync_with_stdio(false) , cin.tie(0) ;
    int n , k ;
    long long ans = 0 ;
    cin >> n >> k ;
    auto cal = [&](int x)
    {
        return 1ll * k * x * (x + 1) / 2 ;
    } ;
    for(int i = 1 ; i <= n ; i ++)  ans += cal(i / k) ;
    cout << ans << '\n' ;
    return 0 ;
}

 

C  小G的约数

牛客练习赛77  部分题解,整除分块即可。

#include<bits/stdc++.h>
using namespace std ;
int main()
{
    std::ios::sync_with_stdio(false) , cin.tie(0) ;
    int n ;
    cin >> n ;
    auto cal = [&](long long l , long long r)
    {
        long long a1 = l ;
        long long n = r - l + 1 ;
        long long d = 1 ;
        return n * a1 + n * (n - 1) * d / 2 ;
    } ;
    auto G = [&](long long n)
    {
        long long ans = 0 ;
        for(long long l = 1 , r ; l <= n ; l = r + 1)
        {
         r = n / (n / l) ;
         ans += 1ll * cal(l , r) * (n / l) ;
        }
        return ans ;
    } ;
    cout << G(G(n)) << '\n' ;
    return 0 ;
}

 

D  小G的LY数对

开局有人牛客练习赛77  部分题解分钟过了,以为直接暴力牛客练习赛77  部分题解做就行,牛客练习赛77  部分题解成瓜皮。

仔细分析牛客练习赛77  部分题解等价于牛客练习赛77  部分题解

具体写的时候要容斥,因为会算重复。

时间复杂度降低为牛客练习赛77  部分题解

#include<bits/stdc++.h>
using namespace std ;
int main()
{
    std::ios::sync_with_stdio(false) , cin.tie(0) ;
    int n , m ;
    cin >> n >> m ;
    vector<int> a(n) ;
    vector<int> b(m) ;
    for(int i = 0 ; i < n ; i ++)  cin >> a[i] ;
    for(int i = 0 ; i < m ; i ++)  cin >> b[i] ;
    vector<int> c , d ;
    for(int i = 0 ; i < n ; i ++)
        for(int j = 0 ; j < 30 ; j ++)
            c.push_back((a[i] ^ (1 << j))) ;
    for(int i = 0 ; i < m ; i ++)
        for(int j = 0 ; j < 30 ; j ++)
            d.push_back((b[i] ^ (1 << j))) ;
    long long ans = 0 ;
    sort(c.begin() , c.end()) ;
    sort(d.begin() , d.end()) ;
    int cur = 0 ;
    int siz1 = c.size() , siz2 = d.size() ;
    for(int i = 0 ; i < siz1 ; i ++)
    {
        int j = i ;
        while(j + 1 < siz1 && c[j + 1] == c[j])  j ++ ;
        while(cur + 1 < siz2 && d[cur] < c[i])  cur ++ ;
        int p = cur ;
        if(c[i] == d[cur])
        {
            while(p + 1 < siz2 && d[p + 1] == d[p])  p ++ ;
            ans += 1ll * (j - i + 1) * (p - cur + 1) ;
            //cout << c[i] << ' ' << j - i + 1 << ' ' << p - cur + 1 << '\n' ;
            cur = p ;
        }    
        i = j ;
    }
    //cout << ans << '\n' ;
    sort(a.begin() , a.end()) ;
    sort(b.begin() , b.end()) ;
    cur = 0 ;
    siz1 = a.size() , siz2 = b.size() ;
    for(int i = 0 ; i < siz1 ; i ++)
    {
        int j = i ;
        while(j + 1 < siz1 && a[j + 1] == a[j])  j ++ ;
        while(cur + 1 < siz2 && b[cur] < a[i])  cur ++ ;
        int p = cur ;
        if(a[i] == b[cur])
        {
            while(p + 1 < siz2 && b[p + 1] == b[p])  p ++ ;
            ans -= 1ll * (j - i + 1) * (p - cur + 1) * 30 ;
            cur = p ;
        }    
        i = j ;
    }

    cout << ans / 2 << '\n' ;
    return 0 ;
}

 

E  小G的GLS图

首先分析是否存在某种数学关系,从而避免建图找割点。但是手画一些牛客练习赛77  部分题解,会发现不建图无法找到割点。

然后就开始思考如何简化建边,不能直接暴力建边牛客练习赛77  部分题解。然后思考质因子分解,每个质因子在牛客练习赛77  部分题解个数存在,直接建边是牛客练习赛77  部分题解的,但是发现我其实只要建出一个长度是牛客练习赛77  部分题解的环就好了,没必要建出稠密图。

因此建出图跑一遍牛客练习赛77  部分题解求割点就好了。

时间复杂度的瓶颈是质因子分解。

#include<bits/stdc++.h>
using namespace std ;
const int maxn = 1e7 + 10 ;
int cnt = 0 ;
bool vis[maxn] ;
int prime[maxn] ;
int id[maxn] ;
void get_prime(int up) //素数筛
{
    memset(vis , 0 , sizeof(vis)) ;
    vis[1] = 1 ;
    for(int i = 2 ; i <= up ; i ++)
    {
        if(!vis[i]) 
        prime[++ cnt] = i , id[i] = cnt ;
        for(int j = 1 ; j <= cnt && i * prime[j] <= up ; j ++)
        {
            vis[i * prime[j]] = 1 ;
            if(i % prime[j] == 0) break ;
        }
    }
}
vector<int> v[700000 + 10] ;
void init(int x , int c)
{
    int now = 1 ;
    for(int i = 1 ; prime[i] * prime[i] <= x ; i ++)
    {
        if(x % prime[i] == 0)  
        {
            while(x % prime[i] == 0)  x /= prime[i] ;
            now *= prime[i] ;
            v[i].push_back(c) ;
        }
    }
    if(x > 1)  v[id[x]].push_back(c) ;
}
int head[maxn] ;
int num = 1 ;
int dfn[maxn] , low[maxn] , parent[maxn];
int ans = 0 ;
int cut[maxn] ;
struct Node
{
    int v , next ;
} edge[maxn] ;
void add(int u , int v)
{
    edge[num].v = v ;
    edge[num].next = head[u] ;
    head[u] = num ++ ;
}
void add1(int u , int v)
{
    add(u , v) ;
    add(v , u) ;
}
void dfs(int u)
{
    static int count = 0 ;
    int children = 0 ;
    int v ;
    dfn[u] = low[u] = ++ count ;
    for(int i = head[u] ; i != 0 ; i = edge[i].next)
    {
        v = edge[i].v ;
        if (dfn[v] == 0)
        {
            children ++ ;
            parent[v] = u ;
            dfs(v) ;
            low[u] = min(low[u] , low[v]) ;
            if(cut[u] == 0 && (parent[u] == -1 && children >= 2 || parent[u] != -1 && low[v] >= dfn[u]))
            {
                ans ++ ;
                cut[u] = 1 ;
                //cout << u << '\n' ;          
            }
            
        }
        else if (v != parent[u])
        low[u] = min(low[u], dfn[v]) ;
    }
}
int main()
{
    std::ios::sync_with_stdio(false) , cin.tie(0) ;
    get_prime(10000000) ;
    int n ;
    cin >> n ;
    for(int i = 0 ; i < n ; i ++)
    {
        int x ;
        cin >> x ;
        init(x , i + 1) ;
    }
    memset(head , 0 , sizeof(head)) ;
    memset(parent , -1 , sizeof(parent)) ;
    memset(dfn , 0 , sizeof(dfn)) ;
    for(int i = 1 ; i <= cnt ; i ++)
    {
        int siz = v[i].size() ;
        if(siz >= 2)
        {
            for(int j = 0 ; j < siz - 1 ; j ++)
                add1(v[i][j] , v[i][j + 1]) ;
            add1(v[i][0] , v[i][siz - 1]) ;
        }
    }
    for(int i = 1 ; i <= n ; i ++)
        if(dfn[i] == 0)  dfs(i) ;
    cout << ans << '\n' ;
    return 0 ;
}

 

F  小G的排列

留坑。

 

上一篇:Oracle - v$lock查询慢原因分析


下一篇:table表格的无缝循环