周二蓝桥杯训练赛
子串分值
反向求解,求每一个字符对答案的贡献是多少,找出一个字符,他前一次出现位置与下一次出现的位置,并记录下来分别为l[i]和r[i],答案就为(i-l[i])*(r[i]-i).
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=100005;
int n;
char s[N];
int r[N],l[N],p[26];
int main(){
scanf("%s",s+1);
n=strlen(s+1);
for(int i=1;i<=n;i++){
int t=s[i]-'a';
l[i]=p[t];
p[t]=i;
}
for(int i=0;i<26;i++){
p[i]=n+1;
}
for(int i=n;i>0;i--){
int t=s[i]-'a';
r[i]=p[t];
p[t]=i;
}
ll ans=0;
for(int i=1;i<=n;i++){
ans+=(ll)(i-l[i])*(r[i]-i);
}
printf("%lld",ans);
return 0;
}
整数拼接
定义一个二维数组s[i][j],用来记录余数,第一个维度由于题中告诉小于10的9次方,所以取9以上的数字。先将不同次方的的余数记录下来,一般第二次便利的时候使用。
#include<bits/stdc++.h>
using namespace std;
const int N=100005;
typedef long long ll;
int n,k;
ll a[N];
ll res;
int s[11][N];
int main(){
scanf("%d%d",&n,&k);
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
for(int i=0;i<n;i++){
ll t=a[i]%k;
for(int j=0;j<11;j++){
s[j][t]++;
t=t*10%k;
}
}
for(int i=0;i<n;i++){
ll t=a[i]%k;
int x=to_string(a[i]).size();
res+=s[x][(k-t)%k];
ll r=t;
while(x--){
r=r*10%k;
}
if(r==(k-t)%k){
res--;
}
}
printf("%lld",res);
return 0;
}
移动距离
先想办法表示出两个数的坐标,然后横坐标相减,纵坐标相减,两者相加即为最短距离。计算时要注意奇数排的最后一个数字的坐标。横轴坐标在偶数排的时候要反推其坐标(因为是S型排列)。
#include<bits/stdc++.h>
using namespace std;
int main(){
int w,m,n,x1,y1,x2,y2,sum=0;
scanf("%d%d%d",&w,&m,&n);
y1=m/w+1;
y2=n/w+1;
if(y1%2!=0){
x1=m%w;
}
else{
x1=w-m%w+1;
}
if(y2%2!=0){
x2=n%w;
}
else{
x2=w-n%w+1;
}
if(m%w==0){
y1-=1;
x1=w;
}
if(n%w==0){
y2-=1;
x2=w;
}
sum=abs(x1-x2)+abs(y1-y2);
printf("%d",sum);
return 0;
}
画中漂流
深搜解决。利用二维数组将时间和剩余的精力建立关系,并逐一进行遍历。当时间剩余i,精力剩余j时,向上游的长度为m-j,向下漂流的程度为i-(m-j)。因此当前位置为d+ (m-j)-(i-(m-j))。只要保证当前位置>0,即可使用 f[i][j] = f[i - 1][j] + f[i - 1][j + 1]。计算后的答案要取模。
#include <bits/stdc++.h>
using namespace std;
const int a=1e9+7;
int f[3005][3005];
int d,t,m;
int main(){
scanf("%d%d%d",&d,&t,&m);
f[0][m] = 1;
for (int i = 1; i <= t; ++i) {
for (int j = 0; j <= m; ++j) {
int len = d + (m - j) - (i - (m - j));
if (len > 0) {
f[i][j] = (f[i - 1][j] + f[i - 1][j + 1]) %a;
}
}
}
printf("%d",f[t][0]);
return 0;
}