牛客练习赛42

A,字符串

https://ac.nowcoder.com/acm/contest/393/A

给定两个等长的由小写字母构成的串 ,其中
现在你需要求出一个子区间  使得  最大,并输出这个值。

表示S和T的最长公共前缀,表示S和T的最长公共后缀。

签到题

#include <bits/stdc++.h>
using namespace std;
#define maxn 200010
int d1[maxn],d2[maxn];
char S[maxn],T[maxn];
int main()
{
    scanf("%s",S+1);
    scanf("%s",T+1);
    int len=strlen(S+1);
    int max1=0;
    int max2=0;
    for(int i=1;i<=len;i++){
        if(S[i]==T[i]){
            d1[i]=d1[i-1]+1;
        }
        if(S[len-i+1]==T[len-i+1]){
            d2[i]=d2[i-1]+1;
        }
        max1=max(max1,d1[i]);
        max2=max(max2,d2[i]);
    }
    printf("%d\n",max1*max2+max1+max2);
    return 0;
}

B,https://ac.nowcoder.com/acm/contest/393/B

注意本题有模数

给定一个 长度为 n 的序列 { a } ,求:

其中  表示异或

官方sol

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define maxn 300010
#define mod 100000007
ll a[maxn];
ll sum[maxn];
ll yhh[maxn];
int n;
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%lld",&a[i]);
        sum[i]=a[i];
        yhh[i]=a[i];
        sum[i]=(sum[i]+sum[i-1])%mod;
        yhh[i]=(yhh[i]^yhh[i-1]);
    }
    printf("%lld\n",(yhh[n]+sum[n])%mod);
    return 0;
}

C题https://ac.nowcoder.com/acm/contest/393/C

对于给出的所有数,按照每个不同的数(权值)进行计算这个数对答案的贡献然后加起来,对于第i行的数x它对答案的贡献应为x*t*(n-a_{1})*(n-a_{2})*.....*(n-a_{i-1})*n^{m-i},其中t为数x在该行出现的次数,a1,a2....等代表第i行之前的各行里面x的出现的次数。乘(n-a_{1})*(n-a_{2})*.....*(n-a_{i-1})是保证了前i-1行里没有与x一致的数,而n^{m-i}表示后面的m-i行即使是有与x一致的数出现 他的贡献也是算在当前的x这里。

#include <bits/stdc++.h>
using namespace std;
#define mod 1000000007
#define maxn 2010
typedef long long ll;
struct node
{
    int x,y;
    bool operator < (const node z) const{
        return x==z.x?y<z.y:x<z.x;
    }
}d[maxn*maxn];
ll f[maxn];
int n,m;
int main()
{
    int cnt=0;
    ll ans=0;
    scanf("%d %d",&n,&m);
    f[0]=1;
    for(int i=1;i<=m;i++) f[i]=f[i-1]*n%mod;
    for(int i=1;i<=m;i++){
        for(int j=1;j<=n;j++){
            int x;
            scanf("%d",&x);
            d[++cnt]=node{x,i};
        }
    }
    sort(d+1,d+cnt+1);
    int fi=1;
    for(int i=1;i<=cnt;i++){
        int t=1;
        if(d[i].x!=d[i+1].x){
            ll s=1;//s是计算(n-a1)*...*(n-ai-1)
            int k=0;//k是计算当前是第几行
        for(int j=fi;j<i;j++){
            if(d[j].y==d[j+1].y)t++;
            else {
                k++;
                ans=(ans+(1ll*d[j].x*t%mod*s%mod*f[m-k])%mod)%mod;
                s=(s%mod*(n-t)%mod);
                t=1;
            }
        }
            fi=i+1;
            ans=(ans+(1ll*d[i].x*t%mod*s%mod*f[m-k-1])%mod)%mod;//把第i个计算进去
     }
    }
    printf("%lld\n",ans);
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值