蓝桥杯2015初赛

本文介绍了两个与赌博游戏相关的算法问题,一是计算不考虑花色和顺序的扑克牌初始组合数,使用了深度优先搜索(DFS)方法;二是解决骰子稳定垒叠的问题,采用了动态规划和矩阵快速幂优化。这两个问题展示了在面对复杂情况时如何运用计算机算法进行求解。
摘要由CSDN通过智能技术生成

牌型种数

defin小明被劫持到X赌城,被迫与其他3人玩牌。 
一副扑克牌(去掉大小王牌,共52张),均匀发给4个人,每个人13张。 
这时,小明脑子里突然冒出一个问题: 
如果不考虑花色,只考虑点数,也不考虑自己得到的牌的先后顺序 
自己手里能拿到的初始牌型组合一共有多少种呢? 

解题思路:这里的点数,是指只考虑每个数字(1~k)的点数组合,而不是总点数的可能组合

用dfs

#include <bits/stdc++.h>
using namespace std;
set<int> st;
int sum = 0;
int cot = 13;
int ans = 0;
void dfs(int d){
    if(d > 13 || cot <= 0){
        if(cot == 0) ans++;
        return;
    }
    for(int i = 0; i<=4; i++){
        if(cot - i >= 0 ){
            cot -= i;
            sum += i*d;
            dfs(d+1);
            sum -= i*d;
            cot += i;
        }
    } 
} 
int main(){
   dfs(0);
   cout<<ans<<endl;
   st.clear();
    return 0;
}

垒骰子

赌圣atm晚年迷恋上了垒骰子,就是把骰子一个垒在另一个上边,不能歪歪扭扭,要垒成方柱体。
经过长期观察,atm 发现了稳定骰子的奥秘:有些数字的面贴着会互相排斥!
我们先来规范一下骰子:1 的对面是 4,2 的对面是 5,3 的对面是 6。
假设有 m 组互斥现象,每组中的那两个数字的面紧贴在一起,骰子就不能稳定的垒起来。 
atm想计算一下有多少种不同的可能的垒骰子方式。
两种垒骰子方式相同,当且仅当这两种方式中对应高度的骰子的对应数字的朝向都相同。
由于方案数可能过多,请输出模 10^9 + 7 的结果。

输入:

        输入存在多组测试数据,对于每组数据:
        第一行两个整数 n m(0<n<10^9,m<=36)
        n表示骰子数目
        接下来 m 行,每行两个整数 a b ,表示 a 和 b 数字不能紧贴在一起。 

输出:

        对于每组测试数据,输出一行,只包含一个数,表示答案模 10^9 + 7 的结果。

输入样例 复制

2 1
1 2

输出样例 复制

544

解题思路:数据量有点大,首先排除dfs等一定会爆掉,不难想到是DP,然后 就是用矩阵快速幂加速,我只能说线性代数好细节。。。我讨厌数学呜呜呜,每次遇到这种二进制,数学的题都卡好久。

#include <bits/stdc++.h>
#define int long long
#define PII pair<int, int>
#define inf 0x3f3f3f 
using namespace std;
const int N = 1e5+10;
const int MOD = 1e9+7;
int op[]={0, 4, 5,6,1,2,3};
int n, m , a, b;
struct Matrix{
	int v[10][10];
	int r, c;
	Matrix(int x, int y, int z){
		r = x; c = y;
		for(int i = 1; i<= x; i++)
			for(int j=1; j<= y; j++)
				v[i][j] = z;
	}
	Matrix(int x){
		r = x; c = x;
		memset(v, 0, sizeof(v));
		for(int i = 1; i<= r; i++)
			v[i][i] = 1;
	}
	
	int sum(){
		int ret = 0;
		for(int i = 1; i<= r; i++)
			for(int j = 1; j<= c; j++)
				ret = (ret + v[i][j]) % MOD;
		return ret;
	}
	
	void print(){
		for(int i = 1; i<=r; i++)
		{
			for(int j =1; j<= c; j++)
			cout<<v[i][j]<<' ';
			cout<<endl;
		}
	} 
};
Matrix matrix_mul(Matrix x, Matrix y){
	Matrix ret = Matrix(x.r, y.c, 0);
	for(int i = 1; i<= x.r; i++)
		for(int j = 1; j<=y.c; j++)
			for(int k = 1; k<= x.c; k++)
				ret.v[i][j] = (ret.v[i][j] + x.v[i][k] * y.v[k][j] % MOD) %MOD;
//	ret.print();
	return ret;
}
Matrix matrix_pow(Matrix x, int y){
	Matrix ret = Matrix(6);//单位矩阵;
//	ret.print();
	while(y){
		if(y & 1) ret = matrix_mul(ret, x);
		x = matrix_mul(x, x);
		y >>= 1;
		//ret.print();
	} 
	return ret;
}
signed  main()
{
	 ios::sync_with_stdio(false);
	 cin.tie(0); cout.tie(0);
	 while(cin>>n>>m){
	 	Matrix x = Matrix(6, 6, 4);
	 	Matrix y = Matrix(6, 1, 4);
//	 	x.print();
//	 	y.print();
	 	while(m -- ){
	 		cin>>a>>b;
	 		x.v[op[a]][b] = x.v[op[b]][a] = 0;//这里也是WA点,对哟要反一下,因为此处只看上面那层的数字作为排列 
		 }
//		 x.print();
		Matrix z = matrix_pow(x, n - 1);//WA点在这, 有一个 矩阵与初始状态的乘积, 如果如果使用z接收会WA, 大小不合适 
		 cout<<matrix_mul(z, y).sum()<<endl;
	 }
	return 0;
} 

1259三羊献瑞

全排列 next_permutation(p, p+10);

1262生命之树

#include<bits/stdc++.h>
#define int long long
#define PII pair<int, vector<int>>
using namespace std;
const int N = 1e5+10;
PII p[N];
int ans[N];
int res = 0;
int n, root;
//当图来做 ,不找根也没事,只要是联通的,不要重复访问父节点就行,然后求算上或者不算上子节点的最大之和,不想要的子节点用0来表示,然后开long long,不然只能过一部分样例
bool st[N];
void dfs(int x, int f){

	for(int i = 0; i< p[x].second.size(); i++){
		int tmp = p[x].second[i];
			if(tmp != f) {
				dfs(tmp, x);
				ans[x] += max((int)(0), ans[tmp]);
			}
	}
	res = max(res, ans[x]);
}
signed main(){
	cin>>n;
	int u, v;
	for(int i = 1; i<= n; i++){
		cin>>p[i].first;
		ans[i] = p[i].first;
	}
	for(int i = 0; i< n-1; i++){
		cin>>u>>v;
		p[u].second.push_back(v);
		p[v].second.push_back(u);
	}
	dfs(1, -1);
	cout<<res<<endl;
	return 0 ;
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值