• 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,先手还是先手,后手还是后手;

  • 相关阅读:
    转 [Lucene.Net] 基本用法
    万商网与Alibaba等的比较
    B2B闯入者 新势力正在崛起
    项目管理随想一
    【转载】/proc目录中的重要信息
    文件名乱码转换器
    C函数调用中对入参取地址引发的问题
    编译通过的代码不算什么,一眼能看懂的代码才算好代码
    Handler使用
    删除system/app下的apk
  • 原文地址:https://www.cnblogs.com/wzxbeliever/p/16099556.html
Copyright © 2020-2023  润新知