A模拟

代码1

#include<bits/stdc++.h>
using namespace std; int n = 101;
int a[120][120];
int ans = 0; int main(){ //填充数组
int t = 0;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
a[i][j] = ++t;
}
}
int cen = n/2+1;
int p = 1;
int l = 1,r=n;
//上半
for(int i=cen;i>=1;i--){
p = l;
while(p<=r){
ans += a[i][p];
p++;
}
l++;
r--;
}
l = 1,r = n;
p = 1;
cen = n/2+1+1;
l++;
r--;
//下半
for(int i=cen;i<=n;i++){
p = l;
while(p<=r){
ans += a[i][p];
p++;
}
l++;
r--;
}
cout<<ans<<endl;
return 0;
}

代码2

B-素数筛法打表+dfs全排列

思路

因为我们需要判断一个数字是否是素数判定次数过多,所以这里使用素数筛法打表,便于查询。

然后我们需要把这 8 个数字全排列,这里和之前的全排列不太一样,这里的全排列第一个数字不能是 0 ,另外我们还需要记录我们全排列的结果。所以我们使用一个数字来记录全排列的结果 num,这样也便于查询是否是素数 。添加一个数字的时候我们通过 10*num + i 完成把先添加的数字放到数字末尾 。

这些细节处理完之后,剩下的就是一个简单的递归了。答案是2668

代码1

#include<bits/stdc++.h>
using namespace std; typedef long long ll; int prime[100000005];
ll ans = 0; //素数筛打表
void Prime(){
for (int i = 2; i <= 100000005; i++) {
prime[i] = true;
}
for (int i = 1; i * i <= 100000005; i++) {
if (prime[i]) {
for (int j = i * i; j <= 100000005; j += i) {
prime[j] = false;
}
}
}
} int visited[10]; //全排列
void dfs(int x,int t){
if(x==8){
//判断是否是素数
if(prime[t]){
// cout<<t<<endl;
ans++;
}
return;
} for(int i=0;i<=7;i++){
if(i==0 && x==0){
continue;
}
if(!visited[i]){
visited[i] = 1;
dfs(x+1,t*10+i);
visited[i] = 0;
}
}
} int main(){
Prime();
memset(visited,0,sizeof(visited));
dfs(0,0);
cout<<ans<<endl;
return 0;
}

代码2

对于第一位数字不能为 0 ,我们可以通过判定 num 是否为 0 来判定第一位数字是否放 0 。



C-dfs搜索



思路1:手算

思路2:dfs

1、用 dfs 求解,每一次搜索,找到两个相同的边界点,标记即可。检测边界点的方法也很简单,只需要一个点的四个方向中有一个点在地图外或者已经被标记,那么这个点就是边界点。

2、检测边界点的方法也很简单,只需要一个点的四个方向中有一个点在地图外或者已经被标记,那么这个点就是边界点。答案是 89。

代码



D-快速幂



答案:pw(x, y / 2, p) * pw(x, y / 2, p) % p

E-末尾零的个数



答案:n = n / 5

对于一个数的阶乘(分解成多个素数相乘),如果想末尾出现 0 的话,只有当 5 和 2 出现的时候,才会在末尾出现 0 。

因为 2 的个数一定比 5 多。所以我们就可以得出一个结论,一个数的阶乘,末尾 0 的个数就是看里面 5 的个数。

现在变成求 1 到 n 的因子有多少个 5。对于包含 1 个 5 的数字,就是 n/5,包含两个 5 的数字个数为 n / 25。。。通过 n = n / 5 的方式,每次剥掉一层 5。

F-bfs+状态压缩







关于bfs+状态压缩:本题是典型的bfs + 状压,一个入口出口,还要拿到地图中多个东西,不知道每个东西拿的先后顺序,而且同一个点重复走的话不好标记,这时候就标记状态。

状态压缩:使用二进制标记状态

思路1

状态压缩 bfs,每个点状态用 d[x][y][state] 表示,state表示每个宝藏是否获取的状态压缩,比如(2<<10)-1 表示十进制的1023 也表示二进制的1111111111,即每个宝藏都拿到了。然后 bfs 即可。

思路2

全排列枚举选取宝藏的顺序,然后用 dfs 求出一个宝藏到另外一个宝藏之间的最短距离。优化的话,就是预处理任意两个宝藏之间的最短路距离。

思路3

手算得到答案48

思路4

1.全排列枚举到达各个宝藏的先后顺序

2.预处理最短距离,bfs算出两两宝藏之间(包括起点/终点)相互到达的最短距离, 并作记录存入ans数组

3.通过全排列枚举的顺序,通过ans数组计算最终距离,每次排列更新最短距离

代码1

ts = s | (1 << (mat[tx][ty] - '0'));//这句话意思就是更新状态(第mat[tx][ty]个宝藏找到了,所以要把它标记为1,怎么标记呢?与s作 | 运算把s的第mat[tx][ty]为置为1)



代码4

#include <i0stream>
#include <cstdi0>
#include <cstring>
#include <alg0rithm>
#include <queue>
#include <wind0ws.h>
using namespace std; /*
1.全排列枚举到达各个宝藏的先后顺序
2.预处理最短距离,bfs算出两两宝藏之间(包括起点/终点)相互到达的最短距离, 并作记录存入ans数组
3.通过全排列枚举的顺序,通过ans数组计算最终距离,每次排列更新最短距离
*/ b00l b00k[10][10];//标记地图上的是否访问过 int bz[11][2] = {0,7,1,6,2,4,3,1,3,8,4,4,6,8,7,6,8,1,9,6,0,0};//每个宝藏的坐标
int Map[10][10]= //整个地图 2表示不能走 1表示宝藏
{
{0,0,0,0,0,0,0,1,0,0},
{0,0,0,2,0,0,1,0,0,0},
{0,2,0,0,1,0,0,2,0,0},
{0,1,0,0,0,2,0,0,1,0},
{0,2,0,0,1,0,2,0,0,0},
{0,0,2,0,0,0,0,2,0,0},
{0,0,0,0,0,2,0,0,1,0},
{0,2,0,2,0,0,1,0,0,0},
{0,1,0,0,0,0,2,2,0,0},
{0,0,2,0,0,2,1,0,0,0}
};
struct n0de
{
int X,y,step;
} N0w,NeXt; int dir[4][2] = {{0,1},{1,0},{0,-1},{-1,0}}; int bfs(int sX,int sy, int eX, int ey)
{
memset(b00k,0,size0f(b00k));
N0w.X = sX;
N0w.y = sy;
N0w.step = 0;
queue<n0de> q;
q.push(N0w);//起点入队
b00k[sX][sy] = true;
while(!q.empty())
{
N0w = q.fr0nt();
q.p0p();
//如果到了 当前理想要到的终点 就返回步数
if(N0w.X == eX && N0w.y == ey)
{
return N0w.step;
}
//搜寻4个方向入队
f0r(int i = 0; i < 4; i++)
{
NeXt.X = N0w.X + dir[i][0];
NeXt.y = N0w.y + dir[i][1];
NeXt.step = N0w.step + 1;
if(NeXt.X >= 0 && NeXt.X <= 9 && NeXt.y >= 0 && NeXt.y <= 9 && Map[NeXt.X][NeXt.y] != 2 && b00k[NeXt.X][NeXt.y] == false)
{
b00k[NeXt.X][NeXt.y] = true;
q.push(NeXt);
}
}
}
return -1;
}
int main()
{
int minn = 999999;
int ans[11][11];//记录宝藏到宝藏(包含起点,起点当作是10号宝藏)的最短路径 //枚举宝藏i 到 宝藏j的最短距离 121次bfs搜索
f0r(int i = 0; i < 11; i++)
{
f0r(int j = 0; j < 11; j++)
{
ans[i][j] = bfs(bz[i][0],bz[i][1],bz[j][0],bz[j][1]);
}
} int num[10] = {0,1,2,3,4,5,6,7,8,9};
d0
{
int sum = 0;
sum += ans[10][num[0]];//起点到第一个点的距离
f0r(int i = 0; i < 9; i++)
{
sum += ans[num[i]][num[i+1]];//宝藏到宝藏每一段路的距离
}
sum += ans[num[9]][10];//终点回到起点的距离
minn = min(minn,sum);//每次排列 更新最小值
}
while(neXt_permutati0n(num,num+10));//枚举10个宝藏到达顺序的全排列
c0ut << minn << endl;
return 0;
}

F-模拟,栈

思路

用栈来维护每次合并完的数,每入栈一个数以后栈顶和次栈顶比较,如果可以合并就合并为新的栈顶,并且再次与次栈顶比较直至无法合并,在合并过程中统计次数即可。

代码

#include<bits/stdc++.h>
using namespace std; stack<int> s;
int n;
int ans = 0; int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
int d;
scanf("%d",&d);
while(!s.empty() && (s.top() - d) == 1){
s.pop();//大的数 去除
ans++;
}
if(!s.empty() && d - s.top() == 1){
ans++;
}else{
s.push(d);//小的数保留
}
}
printf("%d\n",ans);
return 0;
}

H:找规律

#include<bits/stdc++.h>
using namespace std; int n,m; int main(){
cin>>n>>m;
if(n > m){
swap(n,m);
}
//如果只有1行,那么在列上都放上棋子
if(n == 1){
cout<<m<<endl;
}else if(n == 2){
cout<< m / 4 * 4 + min(m%4,2) * 2<<endl;
}else{
cout<< (n * m + 1)/2<<endl;
}
return 0;
}

第一眼以为是dfs暴力搜索,过3组数据,超时了。

#include<bits/stdc++.h>
using namespace std; /*
从左到右、从上到下的顺序dfs搜索 每个格子都有两种可能:放、不放 dfs参数含义:横坐标、纵坐标、当前棋盘上已经放的个数
*/ typedef long long ll; int n,m,ans = 0;
int a[1010][1010];
int dr[8][2] = {{-1,-2},{-2,-1},{-2,1},{1,-2},{2,-1},{-1,2},{2,1},{1,2}}; bool in(int x,int y){
return x>=1 && x<=n && y>=1 && y<=m;
} int valid(int x,int y){
int flag = 1;
for(int i=0;i<=7;i++){
int dx = x + dr[i][0];
int dy = y + dr[i][1];
if(in(dx,dy) && (a[dx][dy] == 1)){
flag = 0;
break;
}
}
return flag;
} void dfs(int x,int y,int t){
if(x==n+1){
ans = max(ans,t);
return;
}
int dx = y>=m ? x+1 : x;
int dy = y>=m ? 1 : y+1; if(in(dx,dy) && a[dx][dy]!= 1 && valid(dx,dy)){
a[dx][dy] = 1;
dfs(dx,dy,t+1);
a[dx][dy] = 0;
}
dfs(dx,dy,t);
} int main(){
scanf("%d%d",&n,&m);
dfs(0,9,0);
printf("%d\n",ans);
return 0;
}

J-计数dp

思路1:dfs回溯+剪枝 过40%数据

#include<bits/stdc++.h>
using namespace std; typedef long long ll; int n,k,ans = 0; /*参数含义:第x个数(不多于k个数),当前剩余值t(初始为n),当前选的数num(小于n的自然数)*/
void dfs(int x,int t,int num){ //第x个数
if(t<0)return;
if(x>k+1)return;
if(x<=k+1){
if(t==0){
ans++;
return;
}
}
if(num>n)return;
//枚举选当前num的个数
for(int i=0;i<=(t/num+1);i++){
if(num*i <=t ){
dfs(x+i,t-num*i,num+1);
}
}
} int main(){
scanf("%d%d",&n,&k);
dfs(1,n,1);
printf("%d\n",ans);
return 0;
}

思路2:计数dp

可设dp[n][k]表示将正整数n分解为不多于k个正整数相加的形式的方案数。根据题意,应分以下4种情况讨论:

1°n=1 或 k=1:n=1时只有"1=1"这1种分解方案;k=1时只有"n=n"这1种分解方案,故方案数=1;

2°n<k:相当于dp[n][k],因正整数n不可能分解为超过n个正整数相加的形式;

3°n>k:根据"是否将n恰好分解为k个正整数相加的形式"(上界),进行讨论:

1°°将n恰好分解为k个正整数相加的形式:此时分解出的每个正整数t都满足t>=1,故相当于将分解出的k个数"都减去1",即相当于dp[n-k][k],也就是将正整数n-k分解为不多于k个正整数相加的形式的方案数;

2°°将n分解为小于k个正整数相加的形式:此时即dp[n][k-1],也就是将正整数n分解为不多于k-1个正整数相加的形式的方案数;

故方案数=dp[n-k][k]+dp[n][k-1];

4°n=k:总体与3°相同,但将n恰好分解为k个正整数相加的形式时,只有"n=n/k+n/k+...+n/k"这1种分解方案,故方案数=1+dp[n][k-1]。

综上,可得以下结论:

#include<bits/stdc++.h>
using namespace std; typedef long long ll;
int n,k;
ll dp[310][310]; int main(){
cin>>n>>k;
for(int i = 1;i<=n;i++){
for(int j=1;j<=k;j++){
//等于1的时候
if(i==1 || k == 1){
dp[i][j] = 1;
}else if(j > i){
dp[i][j] = dp[i][i];
}else if(i > j){
dp[i][j] = dp[i][j-1] + dp[i-j][j];
}else{
dp[i][j] = dp[i][j-1] + 1;
}
}
}
cout<<dp[n][k]<<endl;
return 0;
}

2018 蓝桥杯省赛 B 组模拟赛(五)的更多相关文章

  1. 52-2018 蓝桥杯省赛 B 组模拟赛(一)java

    最近蒜头君喜欢上了U型数字,所谓U型数字,就是这个数字的每一位先严格单调递减,后严格单调递增.比如 212212 就是一个U型数字,但是 333333, 9898, 567567, 313133131 ...

  2. 2016 第七届蓝桥杯 c/c++ B组省赛真题及解题报告

    2016 第七届蓝桥杯 c/c++ B组省赛真题及解题报告 勘误1:第6题第4个 if最后一个条件粗心写错了,答案应为1580. 条件应为abs(a[3]-a[7])!=1,宝宝心理苦啊.!感谢zzh ...

  3. 2015年第六届蓝桥杯C/C++B组省赛题目解析

    一.奖券数目 有些人很迷信数字,比如带“4”的数字,认为和“死”谐音,就觉得不吉利.虽然这些说法纯属无稽之谈,但有时还要迎合大众的需求.某抽奖活动的奖券号码是5位数(10000-99999),要求其中 ...

  4. 计蒜客2018 蓝桥杯省赛 B 组模拟赛(一)

    1,结果填空:年龄 今天蒜头君带着花椰妹和朋友们一起聚会,当朋友们问起年龄的时候,蒜头君打了一个哑谜(毕竟年龄是女孩子的隐私)说:“我的年龄是花椰妹年龄个位数和十位数之和的二倍”. 花椰妹看大家一脸懵 ...

  5. 【2018.10.18】noip模拟赛Day2 地球危机(2018年第九届蓝桥杯C/C++A组省赛 三体攻击)

    题目描述 三体人将对地球发起攻击.为了抵御攻击,地球人派出了 $A × B × C$ 艘战舰,在太 空中排成一个 $A$ 层 $B$ 行 $C$ 列的立方体.其中,第 $i$ 层第 $j$ 行第 $k ...

  6. 2018 蓝桥杯省赛 B 组模拟赛

    C. 结果填空:U型数字 最近蒜头君喜欢上了U型数字,所谓U型数字,就是这个数字的每一位先严格单调递减,后严格单调递增.比如 212 就是一个U型数字,但是 333, 98, 567, 3131,就是 ...

  7. 2019 蓝桥杯省赛 A 组模拟赛(一)-忽明忽暗

    走廊里有 nn 盏灯,编号依次为 1,2,3,...,n,由学校电路控制中心管理.初始时,所有灯都是关闭的.某黑客入侵了学校电路控制中心,黑客想让灯忽明忽暗,进行了 n 轮操作.第 i 轮操作,会让所 ...

  8. 2019 蓝桥杯省赛 A 组模拟赛(一)-修建公路

    题目: 蒜头国有 nn 座城市,编号分别为 0,1,2,3,...,n-1.编号为 x 和 y 的两座城市之间如果要修高速公路,必须花费 x|y 个金币,其中|表示二进制按位或. 吝啬的国王想要花最少 ...

  9. 计蒜客 2019 蓝桥杯省赛 B 组模拟赛(三)一笔画

    #include<iostream> #include<cstring> #include<cstdio> #include<algorithm> us ...

随机推荐

  1. RPC、RMI、SOAP、WSDL、HTTP、TCP/IP

    详情请参考 http://www.jb51.net/article/68971.htm

  2. asp.net GridView增加删除功能

    protected void GridView1_RowDeleting(object sender, GridViewDeleteEventArgs e)    {        string id ...

  3. fzu2204 dp

    2015-10-06 19:31:05 n个有标号的球围成一个圈.每个球有两种颜色可以选择黑或白染色.问有多少种方案使得没有出现连续白球7个或连续黑球7个. 每组包含n,表示球的个数.(1 <= ...

  4. SVM支撑向量机原理

    转自:http://blog.csdn.net/v_july_v/article/details/7624837 目录(?)[-] 支持向量机通俗导论理解SVM的三层境界 前言 第一层了解SVM 1分 ...

  5. Struts2输入校验(XML方式)

    本章主要介绍struts2的XML配置方式输入校验.以下将结合一个实例程序进行说明. 代码结构: 关键代码: RegistAction.javapackage com.alfred.regist.ac ...

  6. php 当前时间 当前时间戳和数据库里取出的时间datetime格式进行比较大小

    php 当前时间 当前时间戳和数据库里取出的时间datetime格式进行比较大小 UNIX时间戳转换为日期用函数: date() ,date('Y-m-d H:i:s', 1500219870); 日 ...

  7. PHP $_SERVER 及用户真实IP

    $_SERVER 是一个包含了诸如头信息(header).路径(path).以及脚本位置(script locations)等等信息的数组.这个数组中的项目由 Web 服务器创建.不能保证每个服务器都 ...

  8. js获取浏览器类型和版本信息

    bro () { let broName = 'Runing' let strStart = 0 let strStop = 0 let temp = '' let userAgent = windo ...

  9. Java开发软件安装及配置

    2017-6-1 1.jdk 1.8.0_131 安装JDK 选择安装目录 安装过程中会出现两次 安装提示 . 第一次是安装 jdk ,第二次是安装 jre .建议两个都安装在同一个java文件夹中的 ...

  10. MyEclipse非正常关闭问题

    问题:电脑突然断电,myeclipse非正常关闭,“Package Explorer”非正常显示,出现错误“Could not create the view: An unexpected excep ...