蓝桥杯 连号区间数
问题描述
小明这些天一直在思考这样一个奇怪而有趣的问题:
在1~N的某个全排列中有多少个连号区间呢?这里所说的连号区间的定义是:
如果区间[L, R] 里的所有元素(即此排列的第L个到第R个元素)递增排序后能得到一个长度为R-L+1的“连续”数列,则称这个区间连号区间。
当N很小的时候,小明可以很快地算出答案,但是当N变大的时候,问题就不是那么简单了,现在小明需要你的帮助。
输入格式
第一行是一个正整数N (1 <= N <= 50000), 表示全排列的规模。
第二行是N个不同的数字Pi(1 <= Pi <= N), 表示这N个数字的某一全排列。
输出格式
输出一个整数,表示不同连号区间的数目。
样例输入1
4
3 2 4 1
样例输出1
7
样例输入2
5
3 4 2 5 1
样例输出2
9
若元素排序后是“连续”数列,则构成方差为1的等差数列,右端点-左端点=最大值-最小值
#include<iostream>
#include<cstdio>
using namespace std;
int a[50010];
int main()
{
int n,sum=0;
scanf("%d",&n);
for(int i=0;i<n;++i)
scanf("%d",&a[i]);
for(int i=0;i<n;++i)
{
int MAX=a[i],MIN=a[i];
for(int j=i;j<n;++j)
{
if(a[j]>MAX)MAX=a[j];
if(a[j]<MIN)MIN=a[j];
if(j-i==MAX-MIN)
++sum;
}
}
printf("%d\n",sum);
return 0;
}
蓝桥杯 幸运数
问题描述
幸运数是波兰数学家乌拉姆命名的。它采用与生成素数类似的“筛法”生成。
首先从1开始写出自然数1,2,3,4,5,6,…
1 就是第一个幸运数。
我们从2这个数开始。把所有序号能被2整除的项删除,变为:
1 _ 3 _ 5 _ 7 _ 9 …
把它们缩紧,重新记序,为:
1 3 5 7 9 … 。这时,3为第2个幸运数,然后把所有能被3整除的序号位置的数删去。注意,是序号位置,不是那个数本身能否被3整除!! 删除的应该是5,11, 17, …
此时7为第3个幸运数,然后再删去序号位置能被7整除的(19,39,…)
最后剩下的序列类似:
1, 3, 7, 9, 13, 15, 21, 25, 31, 33, 37, 43, 49, 51, 63, 67, 69, 73, 75, 79, …
输入格式
输入两个正整数m n, 用空格分开 (m < n < 1000*1000)
输出格式
程序输出位于m和n之间的幸运数的个数(不包含m和n)。
样例输入1
1 20
样例输出1
5
样例输入2
30 69
样例输出2
8
第2个位置上的数是3,第2个幸运数就是3,筛选后第3个位置上的数是7,第3个幸运数就是7,再筛选,第4个位置上的数是9,第4个幸运数就是9,然后筛选,以此类推,维护1到最接近n的幸运数
#include<iostream>
#include<cstdio>
using namespace std;
const int N=1000010;
int a[N];
int main()
{
int m,n,pos=2;
scanf("%d%d",&m,&n);
int len=n,sum=0;
for(int i=1;i<=n;++i)
a[i]=2*i-1;
while(a[pos]<n)
{
int cnt=pos;
for(int i=pos+1;i<=len;++i)
if(i%a[pos])a[++cnt]=a[i];
++pos;
len=cnt;
}
for(int i=1;a[i]<n;++i)
if(a[i]>m)++sum;
printf("%d\n",sum);
return 0;
}
蓝桥杯 数字三角形
问题描述
上图给出了一个数字三角形。从三角形的顶部到底部有很多条不同的路径。对于每条路径,把路径上面的数加起来可以得到一个和,你的任务就是找到最大的和。
路径上的每一步只能从一个数走到下一层和它最近的左边的那个数或者右边的那个数。此外,向左下走的次数与向右下走的次数相差不能超过 1。
输入格式
输入的第一行包含一个整数N(1<N≤100),表示三角形的行数。下面的N行给出数字三角形。数字三角形上的数都是0至100之间的整数。
输出格式
输出一个整数,表示答案。
样例输入
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
样例输出
27
图例请看这篇文章
https://blog.csdn.net/qq_38846700/article/details/116895495?utm_source=app&app_version=4.5.4
从图中可以看出,实现向左下走的次数与向右下走的次数相差不能超过1的路径已经被限制,这些路径的和与动态规划维护的和一样,所以先用动态规划维护数组,然后根据行数的奇偶求出答案
奇数:dp[n][n/2+1]
偶数:max(dp[n][n/2],dp[n][n/2+1])
#include<iostream>
#include<cstdio>
using namespace std;
const int N=110;
int dp[N][N];
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;++i)
for(int j=1;j<=i;++j)
scanf("%d",&dp[i][j]);
for(int i=1;i<=n;++i)
for(int j=1;j<=i;++j)
dp[i][j]+=max(dp[i-1][j-1],dp[i-1][j]);
if(n&1)printf("%d\n",dp[n][n/2+1]);
else printf("%d\n",max(dp[n][n/2],dp[n][n/2+1]));
return 0;
}
蓝桥杯 生日蜡烛
题目描述
某君从某年开始每年都举办一次生日party,并且每次都要吹熄与年龄相同根数的蜡烛。
现在算起来,他一共吹熄了236根蜡烛。
请问,他从多少岁开始过生日party的?
输出
请填写他开始过生日party的年龄数。
答案:26
#include<iostream>
#include<cstdio>
using namespace std;
int main()//假设最多不到200岁
{
for(int i=1;i<200;++i)//i岁开始过生日
for(int j=i;j<200;++j)//现在j岁
if(j*(j+1)-(i-1)*i==472)//j*(j+1)*1/2-(i-1)*(i-1+1)*1/2
cout<<i<<endl;
return 0;
}