四月第二周周报

周二蓝桥杯训练赛

子串分值

反向求解,求每一个字符对答案的贡献是多少,找出一个字符,他前一次出现位置与下一次出现的位置,并记录下来分别为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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值