• 牛客练习赛68(A B C)


    Practice link: https://ac.nowcoder.com/acm/contest/7079


    A : 牛牛的mex

    思路:考虑给出条件:$0<=a{}_{n}<=n-1$ 且每个数字不相同,因此区间 $left[ l,r ight]$ 的mex就是区间 $left[ 1,l-1 ight]$   和 $left[ r+1,n ight]$  中的最小值。

             只需要从前到后 和 从后到前维护两个min。

    代码:

    #include<bits/stdc++.h>
    #define ll long long
    #define MOD 1000000007 
    #define INF 0x3f3f3f3f3f
    #define mem(a,x) memset(a,x,sizeof(a))  
    #define _for(i,a,b) for(int i=a; i< b; i++)
    #define _rep(i,a,b) for(int i=a; i<=b; i++)
    #define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    
    using namespace std;
    const int MAXN = 200005 ;
    inline int rd() 
    {
        int res = 0,flag = 0;
        char ch;
        if ((ch = getchar()) == '-')flag = 1;
        else if(ch >= '0' && ch <= '9')res = ch - '0';
        while ((ch = getchar()) >= '0' && ch <= '9')res = (res<<1) + (res<<3) + (ch - '0');
        return flag ? -res : res;
    }
    int min1[100005],min2[100005];
    int a[100005];
    int n,q;
    int main()
    {
        cin>>n>>q;
        min1[0]=n;
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            min1[i]=min(min1[i-1],a[i]);
        }
        min2[n+1]=n;
        for(int i=n;i>=1;i--){
            min2[i]=min(min2[i+1],a[i]);
        }
        while(q--){
            int l,r;
            scanf("%d %d",&l,&r);
            printf("%d
    ",min(min1[l-1],min2[r+1]));
        }
        return 0;
    }

    B:牛牛的算术

    思路:考虑公式

             $prod^{n}_{i=1} sum^{i}_{j=1} sum^{j}_{k=1} $ = $prod^{n}_{i=1} isum^{i}_{j=1} jsum^{j}_{k=1} k$

             那么因为有阶乘,所以当 n>199999 时,答案为 0 。

             n<199999时,我们看公式,可以用前缀和计算出 1 ~ 199999 的所有答案,推柿子

             ans = $prod^{n}_{i=1} isum^{i}_{j=1} jfrac{j imes (j+1)}{2}$  

             也就是求一个 $x[n]=sum^{n}_{i=1} i imes frac{i imes (i+1)}{2}$ ,最后 $sum[n]=prod^{n}_{i=1} i imes x[i]$ .

    代码:

    #include<bits/stdc++.h>
    #define ll long long
    #define MOD 199999 
    #define INF 0x3f3f3f3f3f
    #define mem(a,x) memset(a,x,sizeof(a))  
    #define _for(i,a,b) for(int i=a; i< b; i++)
    #define _rep(i,a,b) for(int i=a; i<=b; i++)
    #define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    
    using namespace std;
    const int MAXN = 200005 ;
    inline int rd() 
    {
        int res = 0,flag = 0;
        char ch;
        if ((ch = getchar()) == '-')flag = 1;
        else if(ch >= '0' && ch <= '9')res = ch - '0';
        while ((ch = getchar()) >= '0' && ch <= '9')res = (res<<1) + (res<<3) + (ch - '0');
        return flag ? -res : res;
    }
    string s;
    ll x[200005];
    ll num[200005];
    ll p;
    int main()
    {
        int T;
        p=1;
        x[1]=1;
        for(int i=2;i<199999;i++){
            p=p+i;
            x[i]=(1ll*x[i-1]%MOD)+((p*i)%MOD);
            x[i]=x[i]%MOD;
        }
        num[1]=1;
        for(int i=2;i<199999;i++){
            num[i]=(num[i-1]%MOD)*((i*x[i])%MOD);
            num[i]=num[i]%MOD;
        }
        cin>>T;
        while(T--){
            cin>>s;
            if(s.length()>=7){
                printf("0
    ");
            }else{
                int n=0;
                for(int i=0;i<s.length();i++){
                    n=n*10+(s[i]-'0');
                    //cout<<s[i]<<endl;
                }
                //cout<<n<<endl;
                if(n>=MOD){
                    printf("0
    ");
                }else{
                    printf("%lld
    ",num[n]%MOD);
                }
            }
        }    
        return 0;
    }
    
    /*
    1 1*1*1
    2 (1*1*1)*(2*((1+2)+(1+(1+2))))
    3 (1*1*1)*(2*((1+2)+(1+(1+2))))*(3*((1+2+3)*(1+(1+2)+(1+2+3))))
    
    7   1*1+2*3
    25  1*1+2*3+3*6
    
    (1*1)+(2*(1+2))
    (1*1)+(2*(1+2))+(3*(1+2+3))
     */

    C:牛牛的无向图

    思路:首先有 d(u,v)是u到v的最短距离,因此所有点一定是在一棵最小生成树上,其它边都可舍弃。然后考虑最小生成树的加边过程,就是从小到大的,然后我们可以用并查集维护各个连通块,对与某一次合并u和v,因为u和v的距离是w,因此sum[i]就是小于等于w时的数量,也就是sum[i] = sum[i-1]+ siz[fa[u]]*siz[fa[v]] ,其中siz[fa[u]]是点u所在点连通块的点数,最后对每一个L[i]在sum里进行二分查找答案即可。

    代码:

    //#include<bits/stdc++.h>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    #include<string>
    #include<vector>
    #include<stack>
    #include<bitset>
    #include<cstdlib>
    #include<cmath>
    #include<set>
    #include<list>
    #include<deque>
    #include<map>
    #include<queue>
    #define ll long long
    #define MOD 1000000007
    #define INF 0x3f3f3f3f
    #define mem(a,x) memset(a,x,sizeof(a))
    #define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    using namespace std;
    const int maxn=500005;
    inline int rd() {
        int res = 0,flag = 0;
        char ch;
        if ((ch = getchar()) == '-')flag = 1;
        else if(ch >= '0' && ch <= '9')res = ch - '0';
        while ((ch = getchar()) >= '0' && ch <= '9')res = (res<<1) + (res<<3) + (ch - '0');
        return flag ? -res : res;
    }
    /*
    int head[maxn];
    int num=0;
    struct edg{
        int next,to,w;
    }edge[maxn];
    void add_edge(int u,int v,int w)
    {
        num++;
        edge[num].next=head[u];edge[num].to=v;edge[num].w=w;head[u]=num;
        edge[++num].next=head[v];edge[num].to=u;edge[num].w=w;head[v]=num;
    } */
    //-----------
    unsigned int SA, SB, SC;
    int n, m, q, LIM;
    int L[maxn];
    int p[maxn];
    int siz[maxn];
    ll sum[maxn];
    int chosen[maxn];
    struct Node{
        int u,v,w;
    }node[maxn];
    bool cmp(Node x,Node y)
    {
        return x.w<y.w;
    }
    unsigned int rng61(){
        SA ^= SA << 16;
        SA ^= SA >> 5;
        SA ^= SA << 1;
        unsigned int t = SA;
        SA = SB;
        SB = SC;
        SC ^= t ^ SA;
        return SC;
    }
    
    void gen(){
        scanf("%d%d%d%u%u%u%d", &n, &m, &q, &SA, &SB, &SC, &LIM);
        for(int i = 1; i <= m; i++){
            node[i].u = rng61() % n + 1;
            node[i].v = rng61() % n + 1;
            node[i].w = rng61() % LIM;
        }
        for(int i = 1; i <= q; i++){
            L[i] = rng61() % LIM;
            p[i] = L[i];
        }
    }
    int fa[maxn];
    int find(int x)
    {
        return (fa[x]==x)?x:fa[x]=find(fa[x]);
    }
    void merge(int u,int v)
    {
        u=find(u);
        v=find(v);
        if(siz[u]>siz[v]){
            fa[v]=fa[u];
            siz[u]+=siz[v];
        }else{
            fa[u]=fa[v];
            siz[v]+=siz[u];
        }
    }
    int main()
    {
        gen();
        for(int i=1;i<=n;i++){
            siz[i]=1;
            fa[i]=i;
        }
        sort(p+1,p+1+q);
        sort(node+1,node+m+1,cmp);
        int iter=0;
        sum[0]=0;
        for(int i=1;i<=m;i++){
            if(iter==n-1){
                break;
            }
            int u=node[i].u,v=node[i].v,w=node[i].w;
            if(find(u)!=find(v)){
                iter++;
                sum[iter]=sum[iter-1]+1ll*siz[fa[u]]*siz[fa[v]];
                chosen[iter]=w;
                merge(u,v);
            }
        }
        ll ans=0;
        for(int i=1;i<=q;i++){
            int l=0,r=iter,mid;
            while(l<r){
                mid=(l+r+1)>>1;
                if(L[i]>=chosen[mid]){
                    l=mid;
                }else{
                    r=mid-1;
                }
            }
            ans^=sum[l];
        }
        printf("%lld
    ",ans);
        return 0;
    }
    越自律,越自由
  • 相关阅读:
    go函数和方法
    Golang的“面向对象”
    高性能 socket 框架
    wpf 自定义圆形按钮
    WPF 实际国际化多语言界面
    使用过滤器对mvc api接口安全加密
    使用mvc3实现ajax跨域
    WPF,给颜色SolidColorBrush添加动画
    C# 通用验证类 支持 WPF,MVC,Winform
    WSL安装ubuntu搭建vue开发环境(三):docker安装
  • 原文地址:https://www.cnblogs.com/ha-chuochuo/p/13583388.html
Copyright © 2020-2023  润新知