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它对答案的贡献应为,其中t为数x在该行出现的次数,a1,a2....等代表第i行之前的各行里面x的出现的次数。乘是保证了前i-1行里没有与x一致的数,而表示后面的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;
}