1. 程式人生 > 實用技巧 >2020杭電多校第三場

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