牌型种数
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 ;
}