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\n",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\n",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\n",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\n",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!\n");
            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("\n");
        
        for(int i=0;i<=len+10;i++)
        {
            l[i]=0;
            r[i]=0;
        }

    }

    return 0;
}

/*
10
))**
))((
(**)()
*)()
****(
*****)
())***()
(((**()

*/
View Code

猜你喜欢

转载自www.cnblogs.com/MZRONG/p/13397701.html