A - 掌握魔法の东东 II
问题描述:
从瑞神家打牌回来后,东东痛定思痛,决定苦练牌技,终成赌神!
东东有 A × B 张扑克牌。每张扑克牌有一个大小(整数,记为a,范围区间是 0 到 A - 1)和一个花色(整数,记为b,范围区间是 0 到 B - 1。
扑克牌是互异的,也就是独一无二的,也就是说没有两张牌大小和花色都相同。
“一手牌”的意思是你手里有5张不同的牌,这 5 张牌没有谁在前谁在后的顺序之分,它们可以形成一个牌型。 我们定义了 9 种牌型,如下是 9 种牌型的规则,我们用“低序号优先”来匹配牌型,即这“一手牌”从上到下满足的第一个牌型规则就是它的“牌型编号”(一个整数,属于1到9):
同花顺: 同时满足规则 2 和规则 3.
顺子 : 5张牌的大小形如 x, x + 1, x + 2, x + 3, x + 4
同花 : 5张牌都是相同花色的.
炸弹 : 5张牌其中有4张牌的大小相等.
三带二 : 5张牌其中有3张牌的大小相等,且另外2张牌的大小也相等.
两对: 5张牌其中有2张牌的大小相等,且另外3张牌中2张牌的大小相等.
三条: 5张牌其中有3张牌的大小相等.
一对: 5张牌其中有2张牌的大小相等.
要不起: 这手牌不满足上述的牌型中任意一个.
现在, 东东从A × B 张扑克牌中拿走了 2 张牌!分别是 (a1, b1) 和 (a2, b2). (其中a表示大小,b表示花色)
现在要从剩下的扑克牌中再随机拿出 3 张!组成一手牌!!
其实东东除了会打代码,他业余还是一个魔法师,现在他要预言他的未来的可能性,即他将拿到的“一手牌”的可能性,我们用一个“牌型编号(一个整数,属于1到9)”来表示这手牌的牌型,那么他的未来有 9 种可能,但每种可能的方案数不一样。
现在,东东的阿戈摩托之眼没了,你需要帮他算一算 9 种牌型中,每种牌型的方案数。
Input
第 1 行包含了整数 A 和 B (5 ≤ A ≤ 25, 1 ≤ B ≤ 4).
第 2 行包含了整数 a1, b1, a2, b2 (0 ≤ a1, a2 ≤ A - 1, 0 ≤ b1, b2 ≤ B - 1, (a1, b1) ≠ (a2, b2)).
Output
输出一行,这行有 9 个整数,每个整数代表了 9 种牌型的方案数(按牌型编号从小到大的顺序)
Examples
Input
5 2
1 0 3 1
Output
0 8 0 0 0 12 0 36 0
Input
25 4
0 0 24 3
Output
0 0 0 2 18 1656 644 36432 113344
思路:这道题看上去题量比较大,类似于分类一样,将所有可能的情况一一计算,一开始做的时候没看清每种牌只属于后这些类别的一种,所以做的时候考虑的复杂了一些,在得知这些后,我选择的是排列组合的做法,这可能没什么算法可言,但是从上到下,所有情况都是清楚的,我们可以计算出每种情况的种类,详细可以看代码。
#include <iostream>
//1同花顺: 同时满足规则 2 和规则 3.
//2 顺子 : 5张牌的大小形如 x, x?+?1, x?+?2, x?+?3, x?+?4
//3 同花 : 5张牌都是相同花色的.
//4 炸弹 : 5张牌其中有4张牌的大小相等.
//5 三带二 : 5张牌其中有3张牌的大小相等,且另外2张牌的大小也相等.
//6 两对: 5张牌其中有2张牌的大小相等,且另外3张牌中2张牌的大小相等.
//7 三条: 5张牌其中有3张牌的大小相等.
//8 一对: 5张牌其中有2张牌的大小相等.
//9 要不起: 这手牌不满足上述的牌型中任意一个
using namespace std;
int cb(int m,int n)//自定义组合数C(m,n)
{
if(n==0)
{
return 1;
}
int ans=1;
int chushu=1;
for(int i=m;i>m-n;i--)
{
ans=ans*i;
}
for(int i=1;i<=n;i++)
{
chushu=chushu*i;
}
ans=ans/chushu;
return ans;
}
int main()
{
int A,B;
cin>>A;
cin>>B;
int a1,b1,a2,b2;//a代表数字,b代表花色
cin>>a1;
cin>>b1;
cin>>a2;
cin>>b2;
if(a1>a2)//保证a1为较小的
{
swap(a1,a2);
swap(b1,b2);
}
int sum[10];//记录各个情况的数量
for(int i=0;i<10;i++)
{
sum[i]=0;
}
int all=cb(A*B-2,3);//所有情况
bool tonghua=false;
if(b1==b2&&a2-a1<5)//同花顺
{
if(a2-a1==4)
{
sum[1]=1;
}
else if(a2-a1==3)
{
if(A==5)
{
sum[1]=1;
}
else
{
if(a1==0||a2==A-1)//不为第一个或最后一个数
{
sum[1]=1;
}
else
{
sum[1]=2;
}
}
}
else if(a2-a1==2)
{
if(A==5)
{
sum[1]=1;
}
else if(A==6)
{
if(a1==0||a2==A-1)
{
sum[1]=1;
}
else
{
sum[1]=2;
}
}
else
{
if(a1==0||a2==A-1)
{
sum[1]=1;
}
else if(a1==1||a2==A-2)
{
sum[1]=2;
}
else
{
sum[1]=3;
}
}
}
else if(a2-a1==1)
{
if(A==5)
{
sum[1]=1;
}
else if(A==6)
{
if(a1==0||a2==A-1)
{
sum[1]=1;
}
else
{
sum[1]=2;
}
}
else if(A==7)
{
if(a1==0||a2==A-1)
{
sum[1]=1;
}
else if(a1==1||a2==A-2)
{
sum[1]=2;
}
else
{
sum[1]=3;
}
}
else
{
if(a1==0||a2==A-1)
{
sum[1]=1;
}
else if(a1==1||a2==A-2)
{
sum[1]=2;
}
else if(a1==2||a2==A-3)
{
sum[1]=3;
}
else
{
sum[1]=4;
}
}
}
}
if(b1!=b2)//花色不同
{
sum[1]=0;
sum[3]=0;
}
else
{
sum[3]=cb(A-2,3)-sum[1];
}
if(a2-a1>=5)
{
sum[1]=0;
sum[2]=0;
}
else
{
if(a2-a1==4)
{
sum[2]=B*B*B-sum[1];
}
else if(a2-a1==3)
{
if(A==5)
{
sum[2]=B*B*B-sum[1];
}
else
{
if(a1==0||a2==A-1)
{
sum[2]=B*B*B-sum[1];
}
else
{
sum[2]=B*B*B*2-sum[1];
}
}
}
else if(a2-a1==2)
{
if(A==5)
{
sum[2]=B*B*B-sum[1];
}
else if(A==6)
{
if(a1==0||a2==A-1)
{
sum[2]=B*B*B-sum[1];
}
else
{
sum[2]=B*B*B*2-sum[1];
}
}
else
{
if(a1==0||a2==A-1)
{
sum[2]=B*B*B-sum[1];
}
else if(a1==1||a2==A-2)
{
sum[2]=B*B*B*2-sum[1];
}
else
{
sum[2]=B*B*B*3-sum[1];
}
}
}
else if(a2-a1==1)
{
if(A==5)
{
sum[2]=B*B*B-sum[1];
}
else if(A==6)
{
if(a1==0||a2==A-1)
{
sum[2]=B*B*B-sum[1];
}
else
{
sum[2]=B*B*B*2-sum[1];
}
}
else if(A==7)
{
if(a1==0||a2==A-1)
{
sum[2]=B*B*B-sum[1];
}
else if(a1==1||a2==A-2)
{
sum[2]=B*B*B*2-sum[1];
}
else
{
sum[2]=B*B*B*3-sum[1];
}
}
else
{
if(a1==0||a2==A-1)
{
sum[2]=B*B*B-sum[1];
}
else if(a1==1||a2==A-2)
{
sum[2]=B*B*B*2-sum[1];
}
else if(a1==2||a2==A-3)
{
sum[2]=B*B*B*3-sum[1];
}
else
{
sum[2]=B*B*B*4-sum[1];
}
}
}
}
//炸弹4
if(B==4)
{
if(a1==a2)
{
sum[4]=A*B-4;
}
else
{
sum[4]=2;
}
}
if(B>=3)//三带二5,三条7
{
if(a1==a2)
{
sum[5]=(B-2)*(A-1)*cb(B,2)+(A-1)*cb(B,3);
sum[7]=(B-2)*cb(A-1,2)*B*B;
}
else
{
sum[5]=2*cb(B-1,2)*cb(B-1,1);
sum[7]=2*cb(B-1,2)*(A-2)*B+(A-2)*cb(B,3);
}
}
if(B>=2)//两对6 一对8
{
if(a1==a2)
{
sum[6]=(A-1)*cb(B,2)*(A-2)*B;
sum[8]=cb(A-1,3)*B*B*B;
}
else
{
sum[6]=(B-1)*(B-1)*(A-2)*B+2*(B-1)*(A-2)*cb(B,2);
sum[8]=2*(B-1)*cb(A-2,2)*B*B+(A-2)*B*(A-3)*cb(B,2);
}
}
sum[9]=all-sum[1]-sum[2]-sum[3]-sum[4]-sum[5]-sum[6]-sum[7]-sum[8];
for(int i=1;i<=9;i++)
{
cout<<sum[i]<<' ';
}
}