2021蓝桥杯A组

没啥说的枚举

这里用到stl里面的set 来保存每条直线的斜率和截距

点击查看代码
#include<bits/stdc++.h>
using namespace std;
struct point{
	int x;  //横坐标
	int y;  //纵坐标 
};

int main(){
	vector<point> p;   //存放所有点
	for(int i=0; i<20; i++)
		for(int j=0; j<21; j++)
			p.push_back({i,j});
	
	int len = p.size();
	set<pair<double, double> > lines;  //存放直线的斜率与截距
	for(int i=0; i<len; i++){
		for(int j=0; j<len; j++){
			if (p[i].x != p[j].x && p[i].y != p[j].y){  //统计所有斜直线的情况
				double k = (p[j].y - p[i].y) * 1.0 / (p[j].x - p[i].x);
				double b = (p[j].y * (p[j].x - p[i].x) - (p[j].y - p[i].y) * p[j].x) * 1.0 / (p[j].x - p[i].x);
				lines.insert(pair<double, double>(k,b));
			}
		}
	}
	
	cout << lines.size() + 20 + 21 << endl;  //总线=斜线+横直线+竖直线
	return 0; 
}

这个题稍微有些难度

如果题目还要复杂点 不能用计数的方法计算 就要用搜索dfs了

可以跑最短路 也可以线性转移 如果数据大一点就只能线性转移了

点击查看代码
#include<bits/stdc++.h>
#define  MAX 999999999
int path[2100] = {0};
using namespace std;
//两点之间的路径 
long long gcd(int a, int b) {
	if (a % b == 0)
		return b;
	return gcd(b, a % b);
}

long long lcm(int a, int b) {
	return a * b / gcd(a, b);
}

int main(){
	memset(path, 0, sizeof(path));
	for(int i=2; i<=2021; i++)
		path[i] = MAX;
	
	for(int i=1; i<=2021; i++){
		for(int j=i+1; j<=i+21; j++){
			long long edge = lcm(i,j);
			if(path[j] > path[i] + edge)
				path[j] = path[i] + edge;
		}
	}
	
	cout << path[2021] << endl;
    return 0;
}

这个题爆搜可能是不行的 考虑状压dp

点击查看代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
bool v[25][25]; 
ll dp[1<<21][25];
inline int gcd(int a, int b){
	return b==0 ? a : gcd(b, a%b);
}
int main(void)
{
	ll res = 0;
	for(int i = 1;i <= 21; i++){
		for(int j = 1; j <= 21; j++){
		if(gcd(i, j) == 1) 
			v[i-1][j-1] = v[j-1][i-1] = true;
		else
			v[i-1][j-1] = v[j-1][i-1] = false;
	}
	}
	dp[1][0] = 1;
	for(int i = 1; i < (1<<21); i++){
	for(int j = 0; j < 21; j++){
		if(!(i>>j&1)) continue;
		for(int k = 0; k < 21; k++){
			 
			if((i>>k&1) || !v[j][k]) continue;
			
			dp[i+(1<<k)][k] += dp[i][j];
		}
	}
	}
	
	for(int i = 0; i < 21; i++) 
		res += dp[(1<<21)-1][i];
	cout <<res;
	return 0;
} 

如果砝码只能放一边就是一个01背包,但是现在条件是可以放两边 怎么办?

其实就是在原基础上的01背包上加以改进

原先是for(int j=max;j>val[i];j--)

改成 for(int j=max;j>-val[i];j--)

注意数组下标不能为负 所以要整体加一个大整数

还考博弈论 蓝桥杯还是有点难度嘛

这题题目初始a,b都为0,没有表示清楚

首先是很容易想到最高位1的个数的,因为只要谁霸占了最高位的1,不管后面几位怎么弄都是大不过他的

考虑最高位是偶数 那不分上下 肯定是每人占俩 特别的如果每个位置上1的个数都是偶数 那么就是平局 也就是数列异或和等于0

考虑最高位是奇数 那一定有 一个人是偶数个1,一个人是奇数个1,这样奇数个1肯定是胜出 但是还有0要分配啊

分配0同样分为奇偶两种情况

奇数个0,相当于先后手互换 ;

偶数个0,先手还是先手,后手还是后手;

posted @   wzx_believer  阅读(58)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
点击右上角即可分享
微信分享提示