zoukankan      html  css  js  c++  java
  • 2020杭电多校第三场

    http://acm.hdu.edu.cn/search.php?field=problem&key=2020+Multi-University+Training+Contest+3&source=1&searchmode=source

    1004.Tokitsukaze and Multiple

    一个长度为n的序列,用a表示,可以把两个位置连续的数合并多次,每次操作后新元素等于两个旧元素之和,a的长度减少1;

    求对a进行某些操作(或不进行操作)后可以得到的p的倍数的最大可能元素数。

    思路:

    对a数组进行求前缀和并模p,这样如果出现相同的数,则中间的数之和等于p的倍数。

    (回顾另一个前缀和的性质,没有模,直接前缀和:如果某个前缀出现了和前面一个前缀一样的和,那么中间的数的和为0。

    用map记录前缀和并模p的值,如果当前的值出现过,那么就合并,ans++,能合并就合并。

    具体见代码:

    #include <bits/stdc++.h>
    using namespace std;
    const long long mod=1e9+7;
    typedef long long ll;
    const int inf=0x3f3f3f3f;
    const long long INF=0x3f3f3f3f3f3f3f3f;
    const int MAXN=1e5+5;
    const double eps=-1e8;
    typedef pair<int,int>pii;
    ll a[MAXN];
    map<int,int>mp;
    
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--)
        {
    
            mp.clear();
            int n;
            ll p;
            ll sum=0;
            scanf("%d%lld",&n,&p);
            mp[0]=1;
            int ans=0;
            for(int i=1;i<=n;i++)
            {
                scanf("%lld",&a[i]);
                sum=(sum+a[i])%p;
                if(mp[sum]>0)
                {
                    ans++;
                    mp.clear();
                    mp[0]=1;
                    sum=0;
                }
                else mp[sum]++;
            }
            printf("%d
    ",ans);
        }
    
        return 0;
    }
    View Code

    dp做法:

    #include <bits/stdc++.h>
    using namespace std;
    const long long mod =1e9+7;
    typedef long long ll;
    const int inf =0x3f3f3f3f;
    const long long INF =0x3f3f3f3f3f3f3f3f;
    const int MAXN =2e5+5;
    ll  a[MAXN];
    ll sum[MAXN];
    int vis[MAXN];
    int dp[MAXN];
    int main()
    {
    
        int t;
        scanf("%d",&t);
        while(t--)
        {
            int n;
            ll m;
            ll ans=0;
            scanf("%d%lld",&n,&m);
            for(int i=1;i<=n;i++)
            {
                scanf("%lld",&a[i]);
                sum[i]=(sum[i-1]+a[i])%m;
                dp[i]=dp[i-1];
                if(vis[sum[i]]!=0||sum[i]==0)dp[i]=max(dp[i],dp[vis[sum[i]]]+1);
                vis[sum[i]]=i;
            }
            printf("%d
    ",dp[n]);
    
            for(int i=0;i<=n;i++)dp[i]=0,vis[i]=0;
    
        }
    
        return 0;
    }
    View Code

    1005.Little W and Contest

    并查集+组合数。

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    const long long mod =1e9+7;
    typedef long long ll;
    const int inf =0x3f3f3f3f;
    const long long INF =0x3f3f3f3f3f3f3f3f;
    const int MAXN =2e5+5;
    ll fac[MAXN],invfac[MAXN],inv[MAXN];
    
    int f[MAXN];
    ll num[MAXN][5];
    int Find(int n)
    {
        if(f[n]==n)return n;
        f[n]=Find(f[n]);
        return f[n];
    }
    void Union(int a,int b)
    {
        int fa=Find(a);
        int fb=Find(b);
        if(fa!=fb)
        {
            f[fa]=fb;
            num[fb][1]+=num[fa][1];
            num[fb][2]+=num[fa][2];
        }
    }
    void init(int n)
    {
        invfac[0]=1;
        fac[0]=1;
        inv[1]=1;
        for(int i=2;i<=n;++i) inv[i]=((mod-mod/i)*inv[mod%i])%mod;
        for(int i=1;i<=n;++i) fac[i]=fac[i-1]*i%mod,invfac[i]=invfac[i-1]*inv[i]%mod;
    }
    ll C(int n,int m)
    {
        return fac[n]*invfac[m]%mod*invfac[n-m]%mod;
    }
    
    
    int main()
    {
        init(100005);
        int t;
        scanf("%d",&t);
        while(t--)
        {
            int n;
            scanf("%d",&n);
            ll sum1=0,sum2=0;
            for(int i=1;i<=n;i++)
            {
                int a;
                scanf("%d",&a);
                if(a==1)sum1++;
                else sum2++;
                f[i]=i;
                num[i][a]++;
            }
            ll ans=((C(sum2,2)*sum1)%mod+C(sum2,3))%mod;
            printf("%lld
    ",ans);
            for(int i=1;i<n;i++)
            {
                int u,v;
                scanf("%d%d",&u,&v);
                int fu=Find(u);
                int fv=Find(v);
                ll tmp=(((num[fu][2]*num[fv][2])%mod*(sum1-num[fu][1]-num[fv][1]))%mod+((num[fu][2]*num[fv][2])%mod*(sum2-num[fu][2]-num[fv][2]))%mod)%mod;//每次在合并之前算合并后会减少的值
                tmp=(tmp+((num[fu][2]*num[fv][1])%mod*(sum2-num[fu][2]-num[fv][2]))%mod+((num[fv][2]*num[fu][1])%mod*(sum2-num[fu][2]-num[fv][2]))%mod)%mod;
              
                ans=(ans-tmp+mod)%mod;
                printf("%lld
    ",ans);
    
                Union(fu,fv);
            }
            for(int i=1;i<=n;i++)
            {
                num[i][1]=0;
                num[i][2]=0;
    
            }
        }
    
        return 0;
    }
    View Code

    1009.Parentheses Matching

    括号匹配。

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    const long long mod =1e9+7;
    typedef long long ll;
    const int inf =0x3f3f3f3f;
    const long long INF =0x3f3f3f3f3f3f3f3f;
    const int MAXN =2e5+5;
    char a[MAXN];
    char b[MAXN];
    int l[MAXN],r[MAXN];
    int main()
    {
    
        int t;
        scanf("%d",&t);
        while(t--)
        {
            int len;
            scanf("%s",a+1);
            len=strlen(a+1);
    
            int flag=0;
            int l0=0,r0=0;
            int cntl=0;
            for(int i=1;i<=len;i++)
            {
                if(a[i]=='*'||a[i]=='(')
                {
                    l0++;
                    if(a[i]=='(')
                    {
                        l[i]=l[i-1]+1;
                        r[i]=r[i-1];
                    }
                    else
                    {
                        l[i]=l[i-1];
                        r[i]=r[i-1];
                    }
                }
                else
                {
                    r0++;
                    r[i]=r[i-1]+1;
                    l[i]=l[i-1];
                }
                cntl=max(r[i]-l[i],cntl);
                if(r0>l0){flag=1;break;}
    
            }
            r0=0,l0=0;
            for(int i=len;i>=1;i--)
            {
                if(a[i]=='*'||a[i]==')')l0++;
                else r0++;
                
                if(r0>l0){flag=1;break;}
    
            }
            if(flag)
            {
                printf("No solution!
    ");
                continue;
            }
            int cntr=l[len]+cntl-r[len];
            for(int i=1;i<=len;i++)
            {
    
                if(a[i]=='*'&&cntl>0)a[i]='(',cntl--;
            }
    
            for(int i=len;i>=1;i--)
            {
                if(a[i]=='*'&&cntr>0)a[i]=')',cntr--;
            }
            
            for(int i=1;i<=len;i++)
            {
                if(a[i]!='*')printf("%c",a[i]);
            }
            printf("
    ");
            
            for(int i=0;i<=len+10;i++)
            {
                l[i]=0;
                r[i]=0;
            }
    
        }
    
        return 0;
    }
    
    /*
    10
    ))**
    ))((
    (**)()
    *)()
    ****(
    *****)
    ())***()
    (((**()
    
    */
    View Code
  • 相关阅读:
    GIT学习笔记(2):时光机穿梭与远程仓库
    CNN学习笔记:正则化缓解过拟合
    Java分布式:RPC(远程过程调用)
    设计模式:学习笔记(12)——代理模式
    算法:乐观锁与悲观锁
    Python:笔记(5)——错误、调试和测试
    算法:LRU(最近最少使用)
    Python:笔记(4)——高级特性
    方法论:带着问题找答案
    Cache-Aside模式
  • 原文地址:https://www.cnblogs.com/MZRONG/p/13397701.html
Copyright © 2011-2022 走看看