蓝桥杯
注意事项
- 数据范围long long int
- using namespace std;
- 要有输入
十三届蓝桥杯a
求和——公式
选两个数相乘,运用公式:
(
(
a
1
+
a
2
+
a
3
+
.
.
.
+
a
n
)
2
−
(
a
1
2
+
a
2
2
+
a
3
2
+
.
.
.
+
a
n
2
)
)
/
2
((a_1+a_2+a_3+...+a_n)^2-(a_1^2+a_2^2+a_3^2+...+a_n^2))/2
((a1+a2+a3+...+an)2−(a12+a22+a32+...+an2))/2
选数异或
暴力
// a1 @a2=x a1=a2@x
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e5+10;
int a[N],b[N];
int n,m,x;
int main()
{
cin>>n>>m>>x;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=n;i++)
b[i]=a[i]^x;
while(m--)
{
int l,r;
bool flag=0;
cin>>l>>r;
for(int i=l;i<=r;i++)
{ for(int j=l;j<=r;j++)
if(a[j]==b[i])
{
flag=1;
break;
}
if(flag==1) break;
}
if(flag) puts("yes");
else puts("no");
}
}
青蛙过河——二分
一组数据没有过
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int n,x;
const int N=1e5+10;
int a[N];
bool check(int mid)
{
long long int sum=0;
for(int i=0,j=0;i<=n;i++)
{
sum+=a[i];
while(i-j==mid)
{
if(sum<(long long int)2*x) return false;
else
{
j++;
sum-=a[j];
}
}
}
return true;
}
int main()
{
cin>>n>>x;
for(int i=1;i<n;i++)
{
cin>>a[i];
}
int l=1,r=n;
while(l<r)
{
int mid=l+r>>1;
if(check(mid)) //true :跳的小一点
r=mid;
else l=mid+1;
}
cout<<l<<endl;
}
十三届蓝桥杯c
重新排序——差分,排序不等式
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m;
const int N=1e5+10;
int a[N],c[N];
typedef long long LL;
LL res1,res2;
bool cmp(int a,int b)
{
return a>b;
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
cin>>m;
while(m--)
{
int l,r;
cin>>l>>r;
c[l]++,c[r+1]--;
}
for(int i=1;i<=n;i++) c[i]+=c[i-1];
for(int i=1;i<=n;i++)
res1+=(LL)c[i]*a[i]; //转化为LL
sort(a+1,a+n+1,cmp);
sort(c+1,c+n+1,cmp);
// for(int i=1;i<=n;i++) cout<<a[i]<<" ";
// cout<<endl;
for(int i=1;i<=n;i++)
res2+=(LL)c[i]*a[i];
cout<<res2-res1<<endl;
//printf("%d",res2-res1);
}
技能提升——多路归并
鱼塘钓鱼
有 N
个鱼塘排成一排,每个鱼塘中有一定数量的鱼,例如:N=5
时,如下表:
鱼塘编号 1 2 3 4 5
第1分钟能钓到的鱼的数量(1…1000) 10 14 20 16 9
每钓鱼1分钟钓鱼数的减少量(1…100) 2 4 6 5 3
当前鱼塘到下一个相邻鱼塘需要的时间(单位:分钟) 3 5 4 4
即:在第 1
个鱼塘中钓鱼第 1
分钟内可钓到 10
条鱼,第 2
分钟内只能钓到 8
条鱼,……,第 5
分钟以后再也钓不到鱼了。从第 1 个鱼塘到第 2 个鱼塘需要 3 分钟,从第 2 个鱼塘到第 3个鱼塘需要 5分钟,……
给出一个截止时间 T,设计一个钓鱼方案,从第 1个鱼塘出发,希望能钓到最多的鱼。
假设能钓到鱼的数量仅和已钓鱼的次数有关,且每次钓鱼的时间都是整数分钟。
输入格式
共 5 行,分别表示:
第 1 行为 N;
第 2 行为第 1 分钟各个鱼塘能钓到的鱼的数量,每个数据之间用一空格隔开;
第 3 行为每过 1 分钟各个鱼塘钓鱼数的减少量,每个数据之间用一空格隔开;
第 4 行为当前鱼塘到下一个相邻鱼塘需要的时间;
第 5 行为截止时间 T。
输出格式
一个整数(不超过231−1),表示你的方案能钓到的最多的鱼。
数据范围
1≤N≤100,
1≤T≤1000
输入样例:
5
10 14 20 16 9
2 4 6 5 3
3 5 4 4
14
输出样例:
76
#include<iostream>
#include<iostream>
#include<cstring>
using namespace std;
const int N=110;
int a[N],d[N],l[N],spend[N];
//在第k个鱼塘吊的数量
int get (int k)
{
return max(0,a[k]-d[k]*spend[k]);
}
int work(int n,int T)
{
int res=0;
memset(spend,0,sizeof spend);
for(int i=0;i<T;i++)
{
int t=1;
for(int j=1;j<=n;j++ )
if(get(j)>get(t))
t=j;
res+=get(t);
spend[t]++;
}
return res;
}
int main()
{
int n,T;
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i]; //第一分钟各个鱼塘钓到鱼的数量
for(int i=1;i<=n;i++) cin>>d[i]; //每过一分钟鱼塘钓鱼数的减少量
for(int i=2;i<=n;i++)
{
cin>>l[i]; //当前鱼塘到下一个相邻鱼塘的时间
l[i]+=l[i-1];
}
cin>>T; //截止时间
int res=0;
for(int i=1;i<=n;i++) //枚举最终走到哪个鱼塘
res=max(res,work(i,T-l[i]));
cout<<res;
}
十三届蓝桥杯b
填空
九进制转十进制
顺子日期
程序设计
刷题统计
修剪灌木
X进制减法*
进制规定了数字在数位上逢几进一。X进制是一种很神奇的进制,因为其每一数位的进制并不固定!
例如说某种 X 进制数,最低数位为二进制,第二数位为十进制,第三数位为八进制,则 X 进制数 321 转换为十进制数为 65。现在有两个 X 进制表示的整数 A 和 B,但是其具体每一数位的进制还不确定,只知道 A 和 B 是同一进制规则,且每一数位最高为 N 进制,最低为二进制。请你算出 A−B的结果最小可能是多少。
请注意,你需要保证 A 和 B 在 X 进制下都是合法的,即每一数位上的数字要小于其进制。
输入格式
第一行一个正整数 N,含义如题面所述。
第二行一个正整数 Ma,表示 X 进制数 A 的位数。
第三行 Ma 个用空格分开的整数,表示 X 进制数 A 按从高位到低位顺序各个数位上的数字在十进制下的表示。
第四行一个正整数 Mb,表示 X 进制数 B 的位数。
第五行 Mb 个用空格分开的整数,表示 X 进制数 B 按从高位到低位顺序各个数位上的数字在十进制下的表示。
请注意,输入中的所有数字都是十进制的。
输出格式
输出一行一个整数,表示 X 进制数 A−B 的结果的最小可能值转换为十进制后再模 1000000007 的结果。
数据范围
对于 30% 的数据,N≤10;Ma,Mb≤8,对于 100% 的数据,2≤N≤1000;1≤Ma,Mb≤100000;A≥B。
输入样例:11 3 10 4 0 3 1 2 0
输出样例:
94
样例解释
当进制为:最低位 2
进制,第二数位 5
进制,第三数位 11
进制时,减法得到的差最小。
此时 A 在十进制下是 108,B 在十进制下是 14,差值是 94。
统计子矩阵——前缀和,双指针
题目描述
给定一个 N×M 的矩阵 A,请你统计有多少个子矩阵 (最小 1×11×1,最大 N×M) 满足子矩阵中所有数的和不超过给定的整数 K?
输入格式
第一行包含三个整数 N,M和 K。
之后 N 行每行包含 M个整数,代表矩阵 A。
输出格式
一个整数代表答案。
数据范围
对于 30%30% 的数据,N,M≤20,
对于 70%70% 的数据,N,M≤100,
对于 100%100% 的数据,1≤N,M≤500;0≤Aij≤1000;1≤K≤2.5×10^8。输入样例:
3 4 10 1 2 3 4 5 6 7 8 9 10 11 12
输出样例:
19
样例解释
满足条件的子矩阵一共有 1919,包含:
- 大小为 1×11×1 的有 1010 个。
- 大小为 1×21×2 的有 33 个。
- 大小为 1×31×3 的有 22 个。
- 大小为 1×41×4 的有 11 个。
- 大小为 2×12×1 的有 33 个。
前缀和(超时)
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=510;
int n,m,k;
int a[N][N],s[N][N];
int main()
{
cin>>n>>m>>k;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>a[i][j];
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+a[i][j];
int res=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
for(int p=i;p<=n;p++) //注意
for(int q=j;q<=m;q++)
{
int x=s[p][q]-s[p][j-1]-s[i-1][q]+s[i-1][j-1];
if(x<=k)
{
res++;
}
}
cout<<res<<endl;
}
前缀和加双指针
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=510;
int n,m,k;
int a[N][N],s[N][N];
int main()
{
cin>>n>>m>>k;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>a[i][j];
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
s[i][j]=s[i-1][j]+a[i][j];
long long int res=0; //数据范围
for(int i=1;i<=n;i++)
for(int j=i;j<=n;j++)
for(int l=1,r=1,sum=0;r<=m;r++)
{
sum+=s[j][r]-s[i-1][r];
while(sum>k)
{
sum-=s[j][l]-s[i-1][l];
l++;
}
res+=r-l+1;
}
cout<<res<<endl;
return 0;
}
积木画——状态压缩DP
扫雷
李白打酒加强版
砍竹子
十二届蓝桥杯b
填空题
空间
卡片
50%
#include <iostream>
using namespace std;
int n;
bool check(int x)
{
int res=0;
for(int i=1;i<=x;i++)
res+=i;
if(res>=n) return true;
return false;
}
int main()
{
// 请在此输入您的代码
cin>>n;
int l=1,r=n;
while(l<r)
{
int mid=l+r>>1;
if(check(mid)) //大
r=mid;
else l=mid+1;
}
cout<<l<<endl;
return 0;
}
100%
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
int n;
cin>>n;
int res=1;
for(int i=2;;i++)
{
res+=i;
if(res>=n)
{
cout<<i;
break;
}
}
return 0;
}
直线
货物摆放
路径dijkstra
答案10266837
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=3000;
int g[N][N],dist[N];
bool st[N];
int gcd(int a,int b)
{
return b?gcd(b,a%b):a;
}
int lcm(int a,int b) //最小公倍数
{
int x=a*b;
return x/gcd(a,b);
}
int dijkstra()
{
memset(dist,0x3f,sizeof dist);
dist[1]=0;
for(int i=0;i<2021;i++)
{
int t=-1;
for(int j=1;j<=2021;j++)
if(!st[j]&&(t==-1||dist[j]<dist[t]))
t=j;
st[t]=true;
for(int j=1;j<=2021;j++)
dist[j]=min(dist[j],dist[t]+g[t][j]);
}
if(dist[2021]==0x3f3f3f3f) return -1;
return dist[2021];
}
int main()
{
memset(g,0x3f,sizeof g);
for(int i=1;i<=2021;i++)
{
for(int j=i+1;j<=i+21;j++)
{
g[i][j]=lcm(i,j);
g[j][i]=lcm(i,j);
}
}
int t=dijkstra();
cout<<t;
}
程序设计
时间显示
砝码称重
杨辉三角形
双向排序
括号序列
模拟
最大连通——DFS
#include <iostream>
#include<algorithm>
#include<queue>
#define x first
#define y second
using namespace std;
typedef pair<int,int>PII;
int dx[4]={0,0,1,-1},dy[4]={1,-1,0,0};
char g[30][60],a[30][60];
int bfs(int x,int y)
{
queue<PII> q;
q.push({x,y});
g[x][y]='0'; //不要漏了
int res=1;
while(q.size())
{
PII t=q.front();
q.pop();
for(int i=0;i<4;i++)
{
int sx=t.x+dx[i],sy=t.y+dy[i];
if(sx<0||sy<0||sx>=30||sy>=60||g[sx][sy]=='0') continue;
g[sx][sy]='0';
q.push({sx,sy});
res++; //注意
}
}
return res;
}
int main()
{
for(int i=0;i<30;i++) cin>>a[i];
int res=0;
for(int i=0;i<30;i++)
for(int j=0;j<60;j++)
{
memcpy(g,a,sizeof a);
if(a[i][j]=='1')
res=max(res,bfs(i,j));
}
cout<<res;
return 0;
}